We have an aggregate root named Document and a value object named Metadata. There are two types of Domain users i.e. "Data entry operators" and "Regular users". When "Data entry operators" create a Document 4 fields are mandatory out of 20 fields in Metadata but when "Regular Users" create a Document 10 fields are mandatory out of 20 fields in Metadata.
Class Document {
Metadata metadata;
}
We could think of two solutions
Create two separate value objects for "Data entry operators" and "Regular users" and let the value objects do the validation, themselves.
Class OperatorMetadata extends Metadata {}
Class UserMetadata extends Metadata {}
Or, we could create a factory in the aggregate root Document and let it do the validation.
Is there any better way of doing this?
In addition to this, user may want the number of mandatory fields to be configurable, in that case the configuration comes from the DB, how to handle this scenario as well?
You may be over complicating it with the inheritance approach. It also looks like some application specific concepts are leaking into your domain - is there really a concept of 'regular users' in your business domain for this system (there could be, but probably not as it doesn't sound like typical business language or concepts)
Think in terms of the business and not your program and ask "How does this entity come into existence?" For example, if the document belongs in some sort of audit-able document management registry you might use the term 'Lodge' for when someone (who? anyone? employees? specials?) decides to place a document under the control of the registry. This now tells us that we need at least 2 things - information about the person lodging the document, and information about the document as well.
If you are just new Document(params) them into existence you're missing out on the good bits of ddd. Expanding on the assumptions you can align your code to the business as follows.
class document {
private document() {}
documentId Id {get; private set;}
metadata MetaData {get; private set;}
//even with no comments, the types and param names tell me lots about what this does
public static document Lodge(person lodgedBy, metaData lodgementDetails) {
if (ValidateMetaData(lodgedBy,lodgementDetails)) {
return new document() {
Id = documentId.Generate();
MetaData = lodgementDetails;
};
} else {
throw new domainExpceptions.InvalidLodgementException();
}
}
}
If the validation rules are dynamic ("may want" is a massive warning flag that your have not completed your preliminary analysis - stop coding now) then you have a new domain entity 'LodgementValidation'. You could include this in the lodge() parameters, move the lodge() routine to domain service class which orchestrates the now quite a complicate process of document creation or something else more in line with what is actually happen (It might be a purely application layer requirement for a specific UI - maybe the business rules actually don't care about the meta data)
I would recommend re-reading the published literature about DDD. It is more high level methodology and concepts than procedural instructions. Implementation details can and do vary greatly. Sort out your Ubiquitous Language and your Models then go from there; and remember Data Model != Domain Model != Application View Model
Related
I'm reading some data from an excel file, and hydrating it into an object of class A. Now I have to make sure that one of the fields of the data corresponds to the Id of a specific Entity. i.e:
class A{
protected $entityId;
}
I have to make sure that $entityId is an existing id of a specific entity (let's call it Foo). Now this can be achieved using the choice constraint, by supplying the choices option as all of the existing ids of Foo. However this will obviously cause a performance overhead. Is there a standard/better way to do this?
I'm a bit confused about what you are doing, since you seem to talk about Excel parsing, but at the same time you mention choices, which in my opinion relate to Forms.
IMO you should handle directly the relationship to your entity, instead of only its id. Most of the time it is always better to have directly the related entity as attribute of your class A than only the id, and Symfony manipulates such behaviours pretty well.
Then just have your Excel parser do something like this:
$relatedEntity = $this->relatedEntityRepository->find($entityId);
if (!$relatedEntity) {
throw new \Exception();
}
$entity->setRelatedEntity($relatedEntity);
After doing this, since you were talking about Forms, you can then use an EntityType field which will automatically perform the request in database. Use query_builder if you need to filter the results.
I have started working out with Entity Framework (EF) for an MVC n-tier application. It would seem that very obvious that this being a web application (which is stateless), I would have to use detached object models. There is no ambiguity with doing an Add operation. However when doing an edit there are here are two ways
Fetch the original object in context, attach the updated object and
then save to database. Something like mentioned in answer to this
question
EF4 Context.ApplyCurrentValues does not update current values
Set individual modified properties explicitly using the IsModified property of individual fields of the object like
mentioned in this article
http://msdn.microsoft.com/en-us/data/jj592677.aspx
Method 1 has disadvantage of having to load object into memory from database each time an update needs to be performed.
Method 2 would require having to manually pass which fields to be set as IsModified to true from wherever the object an be updated. So for e.g. for each object, I may need to create a boolean collection object for each field of the object.
e.g.
SaveEntity(EntityClass e, EntityStateClass ec)
{
context.Entry(e).Property("Name").IsModified = ec.NameState;
context.SaveChanges();
}
class EntityStateClass{ public bool NameState;}
I would prefer method 2 simply for the sake of performance but I am hindered by the n-tier architecture and repository pattern I am using. My Repository interface restricts save method for any object to be
SaveEntity(EntityClass e);
So I cannot pass the "state" object. Context class is not available and should not be available outside DAL. So I cannot set property outside. Is there any "proper" way to achieve this ?
Note: Self-Tracking Entity is also out of question since I cannot send entities with state to client (the browser) since I am intent on keeping the html lightweight.
EDIT: After a lot of thinking, I am trying to use following mechanism to keep track of modified state for each field in my domain class
Declare a partial class for entity class.
For each field that is updateable, declare a boolean property like "IsModified_FieldName"
Set the "IsModified_FieldName" property when the field is set.
However for this I need Entity Framework to generate explicit properties for me instead of implicit properties that it auto-generates. Does EF provide an handle to do this ?
Here is sample code of what I am trying to achieve
//Save Method for class EntityClass.
SaveEntity(EntityClass e)
{
context.Entry(e).Property("Name").IsModified = e.IsModified_Name;
context.SaveChanges();
}
//EntityClass is class autogenerated by EF
public partial class EntityClass
{
//This is auto-generated property by EF
public string Name {get; set;}
/* This is what I would like EF to do
private string name;
public string Name
{
get {return Name;}
set {
name = value;
//this is what I would like to do
this.IsModified_Name = true;
};
}
*/
}
//This is another partial definition for EntityClass that I will provide
public partial class EntityClass
{
//This property will be set to true if "Name" is set
public bool IsModified_Name {get; set;}
}
PS: It seems the information I have provided is not sufficient and therefore there are no responses.
I am using DbContext (Database first model)
EF auto-generates the class files for me. So each time I update my database, the class files are regenerated.
To your concrete question: The entities are generated by a T4 template and it should be possible to modify this template (which is in text format) to generate the entities in a way you want to shape them.
But I have a few remarks about your concept:
In a web application data are usually changed by a user in a browser. To have a definite knowledge what really has been changed you need to track the changes in the browser (probably by some Javascript that sets flags in the data (a ViewModel for example) when a user edits a text box for instance).
If you don't track the changes in the browser what happens? The data get posted back to the server and you don't know at the server side (with MVC in a controller) which property has been changed. So, your only chance is to map all properties that has been posted back to your EntityClass and every property will be marked as Modified, no matter if the user really did a change or not. When you later call SaveChanges EF will write an UPDATE statement that involves all those properties and you have an unnecessary overhead that you you want to avoid.
So, what did you win by setting individual properties instead of setting the whole entity's state to Modified? In both cases you have marked all properties as Modified. Exceptions are partial changes of an entity, for example: You have a Customer entity that has a Name and City property and a view that only allows to edit the Name but not the City and a corresponding ViewModel that only contains a Name property. In this case your procedure would only mark the Name property of the Customer entity as Modified but not the City. You might save here a little bit because you don't save the City property value to the database. But you still save the Name even if it didn't change.
If you use solution 1 (ApplyCurrentValues) you have to load the entity first from the database, yes, but it would only mark the properties as Modified that really changed compared to their values in the database. If the user didn't change anything no UPDATE would be written at all.
Keep in mind that you are only at the beginning to implement your concept. There are other changes to the data that can happen in the browser than only scalar property changes, namely relationship changes. For example a user changes the relationship from an Order to a Customer or you have a view that has an Order and a collection of OrderItems and the user cannot only edit the Order header but also edit the OrderItems and remove and add new OrderItems. How do you want to recognize when the data come back from the browser to the server which collection item has been added and which has been removed - unless you track all those changes in the browser and send tracking information back to the server in addition to the actual data or unless you reload the Order and OrderItems from the database and merge the changes into the original entities from the database?
Personally I would vote for option 1 for these reasons:
You can use real POCOs that don't carry additional tracking information. (BTW: I have some doubt if you aren't reinventing the wheel by implementing your own tracking that EF change tracking proxies provide out of the box.)
You don't need to track changes in the browser which can become quite complex and will require Javascript in every Edit view to write change flags into hidden form fields or something.
You can use standard features of EF without having to implement your own tracking.
You are required to load entities from the database when you want to update an entity, that's true. But is this the real performance bottleneck in a web application where data have to run through the wire back and forth (and reflection (which isn't really known as to be fast) is involved by the model binder)? I have nothing said if your database is remote from the web server and connected by a 9600 baud modem. But otherwise, your plan is not only premature optimization, it is kind of premature architecture. You are starting to build a potentially complex architecture based on "it could be slow" to solve a performance problem that you actually don't know of whether it really exists.
Lets take a hypothetical project such as a student enrollment system for a music school.
Within the system there needs to exist a way to enter student data for a new student interested in receiving instruction at this school and we can assume that students may have access to this functionality through a web site.
Part of the enrollment process asks the student the type of instrument for which she would like to receive instruction.
As a result of entering information about her preferred musical instrument the behavior will be to assign a default instructor who is assigned to that group of instruments.
Before completing the enrollment request the student will be also be able to change the assigned instructor to different instructor who also is listed as able to give instructed for her selected instrument.
Given this description, the part I'm having a little trouble with is how manage the list of possible instructors out of the ones who are able to give instruction for particular instrument in terms of choosing a default instructor for a new student first, and secondly how to use this same data when it comes time to validate the selected instructor before an enrollment is submitted.
Other technical constraints are that up to this point I've been using a self validating technique very similar to the one presented in Jimmy Nilsson's book Applying Domain-Driven Design and Patterns so it is mainly unclear to me the best way to go about continuing following self validating techniques when access to external data is necessary which I would normally see as outside of the scope of the entity being tested for validity.
The options I'm aware of:
Move validation outside of the entity itself. Perhaps validation is moved into a set of services or a single service per entity which analyses current state of the whole entity and deems it valid or not and provides for domain events or other value objects to be emitted that give more insight about what validation rules have been broken. In this case I'm still a bit uneasy about how the service would get access to the necessary information about instructors
Allow for access to a instructor repository from necessary entities that are attempting to perform this validation.
Create a service that allows access to a list of instructors by instrument category. Alternatively create two separate services, one that returns whether a given instructor is in the list of instructors for a given category, and another which returns the default instructor for a given category.
Load a list of instructor value objects within my aggregate root (likely student, or a student enrollment request) that can be used for validation either by the aggregate root or entities contained within the root.
In either of the first two cases above it seems like the use of a instructor repository would be overkill because I don't need to access an aggregate root that represents an instructor but instead in my case I would see the instructor as a value object that describes the student enrollment request and having a repository spit back value objects seems to be blurring the lines of what a repository is supposed to be doing. For the last two options it seems wrong two allow access to data from a service or a factory in the case of option 4 since aren't repositories supposed to be in charge of data access such as this? And if repositories are the right place for this logic where are the appropriate places to access or store references to repositories? I've been convinced that there are reasons not to access repositories directly within any entity or value object that makes up the model so I'm wondering if this is a case where I may have to bend on that assumption. I should also mention that I'm pretty new to DDD and I'm just now encountering some of my head scratching moments and attempting not to box myself in so any knowledgeable input on this topic would be valuable.
Move validation outside of the entity itself.
One instructor shouldn't know about all other instructors. Validation against set of instructors isn't responsibility of one particular instructor.
Allow for access to a instructor repository from necessary entities that are attempting to perform this validation.
Domain model should be persistence ignorant. Need to break that indicates flaws in Your model.
Create a service that allows access to a list of instructors by instrument category.
This bit of information reveals lack of aggregate root - I would call it InstrumentClass.
Introducing that into Your model would solve some of Your issues. InstrumentClass would hold available instructors that teaches particular instrument.
Next thing You need to figure out is how to describe properly student that is assigned to class. Unfortunately I can't name it at the moment (maybe Participation?). But that entity would be used for InstrumentClass to figure out which instructors are too busy.
Here's my "free-style" (just to show what I see) on modeling Your domain:
using System;
public class Main{
public Main(){
var instructor = new Instructor();
var instrument = new Instrument("saxaphone");
var saxaphoneClass = new InstrumentClass(saxaphone,teacher);
var me=new Person("Arnis");
//here, from UI, I can see available classes, choose one
//and choose according instructor who's assigned to it
var request=me.RequestEnrollment(saxaphoneClass, instructor);
saxaphoneClass.EnrollStudent(request);
}
}
public class Person{
public IList<EnrollmentRequest> EnrollmentRequests { get; private set; }
public EnrollmentRequest RequestEnrollment
(InstrumentClass instrumentClass,Instructor instructor){
if (!instrumentClass.IsTeachedByInstructor(instructor))
throw new Exception("Instructor does not teach this music instrument");
var request=new EnrollmentRequest(this,instrumentClass,instructor);
EnrollmentRequests.Add(request);
return request;
}
}
public class EnrollmentRequest{
public Person Person{ get; private set; }
public InstrumentClass InstrumentClass { get; private set; }
public Instructor Instructor{ get; private set; }
}
public class InstrumentClass{
public void EnrollStudent(EnrollmentRequest request){
var instructor=request.Instructor;
var student=new Student(request.Person);
var studies=new Studies(this,student,instructor);
//TODO: this directiveness isn't good
//student/instructor should listen for class events themselves
//and class should listen if by any reason instructor or student cannot
//participate in studies
student.EnrollInClass(studies);
instructor.AssignStudent(studies);
Studies.Add(studies);
}
public bool IsTeachedByInstructor(Instructor instructor){
return Instructors.Contains(instructor);
}
public InstrumentClass
(Instrument instrument, params Instructor[] instructors){
Instrument=instrument; Instructors=instructors.ToList();
}
public IList<Instructor> Instructors{get;private set;}
public IList<Studies> Studies { get; private set; }
public Instrument Instrument { get; private set; }
}
public class Studies{
public Student Student { get; private set; }
public Instructor Instructor { get; private set; }
public InstrumentClass InstrumentClass { get; private set; }
}
public class Student{
}
public class Instructor{
}
public class Instrument{
}
My answer does not cover the detailed implementation / code as it seems that you are using this as an exercise to learn more about DDD.
Remember that in most cases you'll not be able to get the model right the first time and need to evolve the model. As you “play with it” certain rigid parts will become more flexible to change. (Like a gardening glove as per Eric's analogy). As you gain new insights into the domain, you'll find that you need to introduce new concepts into your model. Using “simple examples” has dangers for example they can lack depth. But simple examples are sometimes needed to get the hang of DDD and fortunately we can evolve the example too ;)
One thing I've heard Eric Evans mention was that if the domain does not feel right or you have trouble expressing something in a model you might be missing a concept. Naturally if you have the concepts in your domain you can “get a feeling” or find a natural place where validation will occur.
Having set the context I thus have a proposition as follow:
Enterprise Patterns and MDA has some complex patterns but the idea you can take away is the CapacityManager of the Inventory archetype as guidance. Unfortunately the model on pg 278 is not available online but have a look at the ServiceInventory archetype.
The instructors are selling their services to students. (Instructors get a salary last time I checked :). If I were to map your example to the Inventory archetype for ideas I would use:
Inventory - List of instruments/courses
ServiceType - Instrument / Course details, start end etc
ServiceInventoryEntry - Instrument + places available (uses capacity manager)
ServiceInstance - Enrollment - place in class (Scheduled, Booked, Canceled, Completed)
CapacityManager (used by ServiceInventoryEntry)
ReservationRequest - Enrollment request
I think the key concept added is the CapacityManager: You can call the ServiceInventoryEntry::getCourses() method which will use the CapacaityManager (service or class) to show you / calculate the available teachers or return the default one. Thus, call it multiple times depending on the context: Default or Propose a list of available places/seats/instructors.
With this model you should be able to find natural place (where and when) to validate. The guidance from Streamlined Object Modeling is to put validation where the data is. Not to be taken as a hard rule but there is a natural tendency for objects to have the proper concerns and data grouped together. For example the capacity manager knows about enrollments and instruments. (From MDA - CapacityManger: Manages utilization of capacity by releasing ServiceInstances)
To get your aggregates see what transactions / changes you'll do so that you can ensure they enforce the invariants (rules). In your example I would make ServiceType(Course) a value object, ServiceInventoryEntry and ReservationRequests aggregate roots. (Depends on how complex you want to take your rules). You can also add Students and Teachers as parties as per the MDA book. I tend to use repositories to get hold of my aggregates and then also rely on inversion of control as per Jimmy's book you referenced.
The reason I like the MDA patterns is that it makes me think of use cases and model concepts that I or the business would not have imagined. But, be careful to only model what you need since the MDA patterns can be big and even enticing. The good thing is that they are designed to be modular or "down scalable".
So in short:
- Your aggregate roots should ensure your domain is in a valid state (Rules / Invariants)
- Put the validation where the data is. Your model will guide your.
How do you apply validation in an MVP/domain environment ?
Let me clearify with an example:
Domain entity:
class Customer
{
string Name;
etc.
}
MVP-model
class CustomerModel
{
string Name;
etc.
}
I want to apply validation on my domain entities but the MVP model has it's own model/class
apart from the domain entity, does that mean I have to copy the validation code
to also work on the MVP-model?
One solution I came up with is to drop the MVP-model and use the domain entity as MVP-Model,
but I don't want to set data to the entities that isn't validated yet.
And second problem that rises is that if the entity has notify-events,
other parts of the application will be affected with faulty data.
A third thing with that approach is if the user edits some data and then cancels the edit, how do I revert to the old values ? (The entity might not come from a DB so reloading the entity is't possible in all cases).
Another solution is to make some sort of copy/clone of the entity in question and use the copy as MVP-model, but then it might get troublesome if the entity has a large object graph.
Anyone has some tips about these problems?
Constraining something like the name of a person probably does not rightfully belong in the domain model, unless in the client's company there is actually a rule that they don't do business with customers whose names exceed 96 characters.
String length and the like are not concerns of the domain -- two different applications employing the same model could have different requirements, depending on the UI, persistence constraints, and use cases.
On the one hand, you want to be sure that your model of a person is complete and accurate, but consider the "real world" person you are modeling. There are no rules about length and no logical corollary to "oops, there was a problem trying to give this person a name." A person just has a name, so I'd argue that it is the responsibility of the presenter to validate what the user enters before populating the domain model, because the format of the data is a concern of the application moreso than the domain.
Furthermore, as Udi Dahan explains in his article, Employing the Domain Model Pattern, we use the domain model pattern to encapsulate rules that are subject to change. That a person should not a have a null name is not a requirement that is likely ever to change.
I might consider using Debug.Assert() in the domain entity just for an added layer of protection through integration and/or manual testing, if I was really concerned about a null name sneaking in, but something like length, again, doesn't belong there.
Don't use your domain entities directly -- keep that presentation layer; you're going to need it. You laid out three very real problems with using entities directly (I think Udi Dahan's article touches on this as well).
Your domain model should not acquiesce to the needs of the application, and soon enough your UI is going to need an event or collection filter that you're just going to have to stick into that entity. Let the presentation layer serve as the adapter instead and each layer will be able to maintain its integrity.
Let me be clear that the domain model does not have to be devoid of validation, but the validation that it contains should be domain-specific. For example, when attempting to give someone a pay raise, there may be a requirement that no raise can be awarded within 6 months of the last one so you'd need to validate the effective date of the raise. This is a business rule, is subject to change, and absolutely belongs in the domain model.
I'm building some repositories for an MVC application, and I'm trying to come up with the right way to divide responsibilities between repositories. In most cases, this is obvious. But there is one particular case where I'm not sure what the right answer is.
The users of this application need to track multiple types of time for their employees. For simplicity, let's consider only two. I'll call them "time cards" and "attendance." The exact nature of the difference between these two is not really important, but you should note that the end-users consider them entirely separate data. I think, though, that the reason they consider them entirely separate data is that they have never really had the opportunity to see them together in the past. Both types of records have almost entirely different business rules concerning editing the records, but they are also, generally speaking, both records of where an employee was at a particular time. Both types of time records have a great deal of properties in common, such as a total number of hours, and an employee for whom the time was collected. Both types also have a few properties which are completely unique to the individual type. We're keeping these "extra" properties in an instance of another type. So the general structure looks like this:
class TimeRecord
{
Person Employee { get; set; }
TimeSpan? Hours { get; set; }
}
class TimeCardData
{
TimeRecord Record { get; set; }
TProperty TimeCardProperty { get; set; }
}
class AttendanceData
{
TimeRecord Record { get; set; }
TProperty AttendanceProperty { get; set; }
}
So the question is, How many repositories are required here?
1 Repository
A design with only one repository would expose methods to return "time cards", "attendance" records, or both types in one list. This is fairly convenient for clients of the repository, but, to my mind, has a real danger of becoming a very fat class. I think that a repository for just "time cards" is already going to be one of the largest repositories in the system even without also handling "attendance" simply due to the complex business rules involved.
2 Repositories
Another design would have one repository for "time cards" and another repository for "attendance" records. This has the advantage that the business rules for, e.g., "time cards" are in a place by themselves. But I'd also like to have a way to get a list of all time records, regardless of type. It's not clear which repository to use for this case. Both?
3 Repositories
A design with one repository for "time cards", another repository for "attendance" records, and a third repository to deliver a read-only list of all time records is also a possibility. Like the 2 repository design, this has the advantage that the business rules for, e.g., "time cards" are in a place by themselves. It's now clear where to get the combined list. But I find it a bit weird that I could get the same record from two different repositories.
Hybrid
A hybrid approach would use a single repository, but move any business rules code (including selection of records) into separate types. In this example, a single "time record repository" would aggregate instances of business rule implementation classes for "time card" and "attendance" time. I think this is the approach I'm favoring right now.
Other?
Anything I've missed? Any compelling arguments for one design over the other?
Repositories are, at least not to my knowledge, a place for business rules. They are just a facade meant to mimic a collection; underneath they're basically pure data access (if that's they're job, you may not be persisting anything with a Repository as well). So separate repositories should not be considered for "business rules" reasons.
If your domain objects are really separate objects, then you should have separate repositories. Remember what a repository is: it's a facade. It mimics a collection to your domain. See here for a really good blog post on Repositories: http://devlicio.us/blogs/casey/archive/2009/02/20/ddd-the-repository-pattern.aspx
The repository is a facade; an abstraction.
That said... I do not think you have separate objects. You've got some issues here that have nothing to do with repositories and everything to do with the domain and the design of the domain. Are the two types of "timecards" actually two different things, or are they really the same?
You say, "But I find it a bit weird that I could get the same record from two different repositories."
That tells me that they are actually the same data, expressed in different ways. And there are ways to handle that.
If this is really the case, then what you have here is subclasses of a common base class (something that can be modeled in a DB pretty easy and handled elegantly with NHibernate, for instance).
I'll give you an example of a project I am working on. I have something called a "Broadcast". It's a base class; abstract. Can't be instantiated. I have two specific concrete types of this class: DeviceBroadcast and FileBroadcast. One streams audio/video from a device (like a DirectX capture card) and one streams audio/video from a file source (like an .mp3).
I have one repository that returns a Broadcast object. I can cast it to a FileBroadcast to manipulate specific information about a FileBroadcast, or I can cast to a DeviceBroadcast for the same reason - if it is of that type. A Broadcast cannot be both a FileBroadcast and DeviceBroadcast type. It has to be one or the other.
In the database I store the generic broadcast parameters in a Broadcast table, and then I store the file specific properties in a FileBroadcast table. Same goes for the DeviceBroadcast table; separate. When I query via the Repository, however, I just want Broadcasts. That's my root aggregate object and thus that's my repository.
The Broadcast base class has common methods that both subclasses use (like the GetCommand() method, which returns a specific command-line argument to launch a VLC process). Subclasses have to override and implement that method because it's abstract. In this way, the "business logic" that is unique to a FileBroadcast is contained in the FileBroadcast class. The "business logic" that is unique to a DeviceBroadcast is contained in the DeviceBroadcast class. Any logic that is common to both is contained in the superclass, Broadcast.
You seem to have a similiar situation here and that's why I am sharing my design. I think it might serve you well.
Above all, think about your domain and the data. If you are going to get duplicate data by way of separate repositories, then you need to give more thought to how you're designing the domain. Don't let the users dictate your domain design either. They know the domain from their perspective. All you have to do is be able to present the data to them in a way they understand. That doesn't mean you have to have a bad design; You can have a good design behind the scenes because your code is the thing that has to use the domain.