Lets abstract say i want to program two classes that have a relation of 1 to n(many) and I don't know what the best approach to take. Programming Language doesn't matter!!!
class Parent
{
string name;
date birthdate;
array children[]; // is it better to declare here an array of children and add childrenobjects to >this or is it better at the childclass to have an variable pointer to an object of type Parent????
... constructor setters getters ....
function addChild(Childtype childvar)
{
this->children push childvar
}
function removeChild(Childtype childvar)
{
}
function saveDB()
{
//what do I save there only parent or also the children that were created during runtime >and added to an instance of this object????
insert into relational_db_table values (name, birthdate);
//really not sure whats the best and why
foreach key->value of children do
{
child->saveDB()
}
}
}
class Child {
Parent myparent;
string name;
string description;
....constructors setters getters... //doesnt matter
saveDB { //
INsert into relational_db_table VALUES (name, description, myparent);
}
}
So i will repeat now my 2 questions:
1. What is best and why?
a) to declare at the parent class an array which holds the children
b) to declare a variable at the child class that holds a reference to the parent object
c) do both of the above
Regarding saving to databases what is the best and why?
If i take a) form 1st question approach do i have to save the children as i wrote from the parent class cause i cant see how else i can save the children to the db for later use. is here any othere method??
If I take b I will have to manage somehow the childrens of a parent in memory that will be don with a collection no problem extra which is not a problem. but in this case if anything changes to a propery i can save it separatly hmmm not sure.
Please thing of these questions with a database in the back of the application the database is not necessary a relational one its fine for me also with nosql databases. I'm only interested to do design these classes very good so in future if something has to be changed the things will be easy to change and i want do use the best programming patterns possible. I have read also almost all of the existing OOP programing patterns around but i still cant decide what to do here best.
PS: sorry code is not tabbed
Thanks alot!
I would go with first approach,
class Parent {
private String id;
private List<Child> childList;
public List<Child> getChildList() {
return childList;
}
public String getId() {
return id;
}
}
class Child {
private String id;
public String getId() {
return id;
}
}
You can insert data of multiple parent as,
List<Parent> parentList = getParentList();
for (Parent parent : parentList) {
String parentId = parent.getId();
for (Child child : parent.getChildList()) {
String childId = child.getId(); // Parent info
// Add to DB - you can pass parent info & child info
// insert parentId, childId
}
}
Why not each child having reference to its parent?
In this case, you need to have a list which contain children, which will break OOPS concept. (For Eg: Parent, as an object need to know about its children)
How is it useful for DB?
In this case, you can easily navigate to required parent (If not require for now, for future) & insert ONLY its corresponding children elements into DB. If you take option 2, you need to loop over ALL child elements (Which may be VERY long - Not efficient)
Were would you place the functions to insert the data into the database?
Commented in code.
Related
In DDD, Entities have this concept of identity that uniquely identifies every instance regardless of all the other properties. Usually this identity has to be unique among the BC in which the Entity live, but there is an exception.
Sometimes we need to create Aggregates that are not only made by the root Entity and some Value Objects but have one or more child / nested Entities (that I understand to be called local Entities). For this kind of Entities the identity has only to be locally unique i.e. unique among the Aggregate boundaries.
Given this, let's also consider the fact that are two way to model a has-a relationship in DDD, depending on the actual business needs: separate Aggregates or Aggregate Root + child Entities.
In the first case the "child" Aggregate of the relation has a reference to the identity of the parent one, which in turn usually has a factory method to create and return an instance of the child:
class ForumId extends ValueObject
{
// let's say we have a random UUID here
// forum name is not a suitable identifier because it can be changed
}
// "parent" aggregate
class Forum extends AggregateRoot
{
private ForumId _forumId;
private string _name;
method startNewThread(ThreadId threadId, string title): Thread
{
// make some checks, maybe the title is not appropriate for this forum
// and needs to be rejected
...
// passing this forum's ID,
return new Thread(this->_forumId, threadId, title)
}
}
class ThreadId extends ValueObject
{
// let's say we have a random UUID here
// thread title is not a suitable identifier because it can be changed
}
// "child" aggregate
class Thread extends AggregateRoot
{
private ForumId _forumId;
private ThreadID _threadId;
private string _title;
}
If we consider instead the second case, let's say because for some business reason we need to have Thread as a local entity of Forum, what is the correct way to identify it? Should Thread still contain the ForumId of the parent Forum or it is redundant since it will only live inside that specific Forum and never accessed outside?
Which way is better and more importantly why? May the data model (i.e. the database level) steer the decision toward one way or another, or should we still ignore it as per good DDD design?
class Forum extends AggregateRoot
{
private ForumId _forumId;
private string _name;
private List<Thread> _threads;
method startNewThread(string title): ThreadId
{
// or use and injected `ThreadIdentityService`'s `nextThreadId(ForumId)` method
var threadId = this.generateNextLocalThreadId()
var newThread = new Thread(/*this->_forumId, */ threadId, title)
this._threads.append(newThread)
return threadId
}
}
// "child" aggregate - case 1
class Thread extends LocalEntity
{
private ForumId _forumId;
private ThreadID _threadId;
private string _title;
}
// "child" aggregate - case 2
class Thread extends LocalEntity
{
private ThreadID _threadId;
private string _title;
}
So the main purpose of having an aggregate is to make any change to this aggregate atomic.
The aggregate root contains the full child entity inside, for example Forum would have a collection of Threads.
Since the Thread is already inside a Forum wouldn’t make any sense having ForumId inside since the repository in charge of saving it would already know that id because we’d save the whole forum not a single thread.
Also wanted to add that Forum aggregate seems to be a huge aggregate, that implies some trade offs that you should take into account.
In a bounded context I created an Entity which serves as an aggregate for other objects in this context. The problem is, an instance of an Entity may be in child-parent relation with another Entity. In terms of a database it means, that there is a parent_id field which references a row in the same entities table.
And the question is, from DDD point of view, is it ok to make an instance of an Entity an argument of its own constructore function? Or is better to use an aggregate root (or an Entity identifier). So, which way is better:
class Entity {
public constructor (arg1, arg2, Entity parent) {
...
this.setParent(parent);
}
}
or this way:
class Entity {
public constructor (arg1, arg2, int parent_id) {
...
this.setParentId(parent_id);
}
}
Just because you have a tree like structure doesn't mean that all Entities in this structure should be part of the same Aggregate.
You can design your system to have each Entity instance in it's own aggregate. Since each entity has a parent you have to reference this parent.
One way to do this is to have an Object reference like in your first example
Another way is to use Reference by identity like in your second example
If you use Object reference that means that you must load all the objects referenced together from the DB. This may cause you to load huge amount of them. If you application doesn't require you to do so it's best avoided.
If you choose to use Object reference then you can pass an Entity to the Constructor like in your ecample.
If you use Reference by ID you can only load one object, then if needed, you can load another by using the ID. This is useful if you want to have multiple aggregates that only need each other in specific situations and you don't need to load them all the time together because your application doesn't require you to do so.
Here's an example:
public TreeNode {
public Guid ParentID { get; private set; }
}
public void DoSomethingToNode(Guid nodeId) {
var node = TreeNodeRepository.GetById(nodeId);
var parent = TreeNodeRepository.GetById(node.ParentID);
// do stuff with parent and child.
}
If you haven't read the DDD book, I recommend it.
This essay from Vaughn Vernon is also great on modeling aggregates
I have a situation where the child to be able to reference the parent. The reason for this is that I want the child to have the ability to update the parent object.
configuration.Range.Next(configuration)
I do not want to pass the parent object reference instead the Range object should be able to find its parent object. How would I do this?
Class Range { ....MethodX(){How do I access the Configuration Object here } }
Class Configuration { public Range range{get;set;} ..... }
Part of the difficulty with answering your question is that people use the terms "child" and "parent" to mean different things to different people.
One of the most common uses of the terms is as synonyms for subclass (child) and superclass (parent) in an inheritance structure. Assuming that is your meaning, you already have access to anything from the superclass (i.e. "parent") that is declared as public or protected. For example:
public class Parent
{
protected int Foo { get; set; }
}
public class Child : Parent
{
public void DoSomething()
{
Foo = 42;
// or
base.Foo = 42;
}
}
If this isn't the situation you're working with please add more information to your original question to better describe what you mean when you use the terms "child" and "parent."
I have an aggregate that includes the entities A, AbstractElement, X, Y and Z. The root entity is A that also has a list of AbstractElement. Entities X,Y and Z inherit from AbstractElement. I need the possibility to add instances of X, Y and Z to an instance of A. One approach is to use one method for each type, i.e. addX, addY and addZ. These methods would take as arguments the values required to create instances of X, Y and Z. But, each time I add a new type that inherits from AbstractElement, I need to modify the entity A, so I think it's not the best solution.
Another approach is to use an abstract add method addAbstractElement for adding AbstractElement instances. But, in this case, the method would take as argument an instance of AbstractElement. Because this method would be called by entities located outside of the aggregate, following DDD rules/recommandations, are these external entities authorized to create instances of AbstractElement? I read in the Eric Evans book that external entities are not authorized to hold references of entities of an aggregate other than the root?
What is the best practice for this kind of problem?
Thanks
From Evan's book, page 139:
"if you needed to add elements inside a preexisting AGGREGATE, you might create a FACTORY METHOD on the root of the AGGREGATE"
Meaning, you should create a factory method on the root (A) which will get the AbstractElement's details. This method will create the AbstractElement (X/Y/Z) according to some decision parameter and will add it to its internal collection of AbstractElements. In the end this method return the id of the new element.
Best Regards,
Itzik Saban
A few comments. As the previous answerer said, it's a good practice to use a factory method. If you can avoid it, never create objects out of the blue. Usually, it's a pretty big smell and a missed chance to make more sense out of your domain.
I wrote a small example to illustrate this. Video is in this case the aggregate root. Inside the boundaries of the aggregate are the video object and its associated comments. Comments can be anonymous or can have been written by a known user (to simplify the example, I represented the user by a username but obviously, in a real application, you would have something like a UserId).
Here is the code:
public class Video {
private List<Comment> comments;
void addComment(final Comment.Builder builder) {
this.comments.add(builder.forVideo(this).build());
// ...
}
}
abstract public class Comment {
private String username;
private Video video;
public static public class Builder {
public Builder anonymous() {
this.username = null;
return this;
}
public Builder fromUser(final String username) {
this.username = username;
return this;
}
public Builder withMessage(final String message) {
this.message = message;
return this;
}
public Builder forVideo(final Video video) {
this.video = video;
return this;
}
public Comment build() {
if (username == null) {
return new AnonymousComment(message);
} else {
return new UserComment(username, message);
}
}
}
}
public class AnonymousComment extends Comment {
// ...
}
static public class UserComment extends Comment {
// ...
}
One thing to ponder on also is that aggregate boundaries contain objects and not classes. As such, it's highly possible that certain classes (mostly value objects but it can be the case of entities also) be represented in many aggregates.
Using Windows Azure Table Storage (WATS) and trying to update the app to use Azure. I've read many articles, and am not sure on the best approach for this, that is parent to child in a self referencing model.
ie a single parent message could have many child sub-messages. In a DB model, it would be a self referencing table.
How would I best structure this for WATS so that when I make a query "Give me 10 parent records", it will also return all the child-messages belonging to the parent...
The entity of the message / submessage as below. I've tried to define the PK and RK as below:
public class TextCacheEntity : AzureTableEntity // custom table inherits AzureTableEntity
{
public override void GenerateKeys()
{
PartitionKey = string.Format("{0}_{1}_{2}", MessageType, AccountId.PadThis(), ParentMessageId );
RowKey = string.Format("{0}_{1}", DateOfMessage.Ticks.ReverseTicks(), MessageId);
}
public string MessageType { get; set; }
public int AccountId { get; set; }
public DateTime DateOfMessage { get; set; }
public string MessageId { get; set; }
public string ParentMessageId { get; set; }
// other properties...
}
I thought of an implementation so the child messages store the parentMessagesId, and the parent parentMessageId would be empty.
The pattern would then be
Get the parent messages
.Where(o => o.ParititionKey == "Parent_000000000000001_").Take(10)
Get the child messages. Iterate through all the parent messages and using a parallel for loop
.Where(o => o.ParititionKey == "Child_000000000000001_" + parentMessageId)
But the problem is that this will result in 11 queries !
See this example by Scott Densmore:
http://scottdensmore.typepad.com/blog/2011/04/multi-entity-schema-tables-in-windows-azure.html
You can do this by using the same PK for both. There are a couple reasons to do this, but one good one is that you can then also issue batch commands for parent and children at once and achieve a type of consistent transaction. Also, when they share the same PK within the same table, it means they are going to be colocated together and served from the same partition. You are less likely to continuation tokens (but you should still expect them). To differentiate between parent and children you can either add an attribute or use the RowKey perhaps.
The only trick to this (and the model you already ahve), is that if the parent and children are not the same CLR type, you will have issues with serialization in WCF DataServices. You can fix this of course by creating an uber-CLR type that has both child and parent properties or you can override serialization with the ReadingEntity event and handle it yourself.
Anyhow, use the same PK for both children and parent. Then when you search PK ranges you will always get parents and children returned at once (you can discriminate with a Where clause predicate if you wish).