DDD: Should 'country' be a Value Object or an Entity? - oop

'country': Value Object or Entity in DDD?
Opinions either way appreciated.
And, where to store the table of country names/codes?
DB?
XML?
In a class?
Thanks!

If your domain is geographic or political, then it might be an entity, but in the average case, a country is just a value associated with things like addresses. In that case, in the context of your object model, it's just a value.
As for storage, the domain model doesn't really care. You can use the database if it's convenient, XML if you prefer, and a class if you have behavior associated with countries.

One of the characteristics of an entity is that it has a life cycle, i.e. it changes over time. A value object does not. In fact, value objects should be immutable. So the question to ask yourself is, "Does the country object change over time?"
Another aspect which differentiates entities and value objects is that two value objects with the same properties are the same. So if you have an instance of country with the name "France", it's the same as another instance of country with the name "France", even though they are two distinct instances (assuming that's the only property of country for the sake of this discussion). Think of strings in most languages, the string "fubar" equals another instance of the string "fubar".
Entities, on the other hand, are distinct even if they have the same properties. One customer with the name "John Smith" may not be the same as another customer with the name "John Smith".
So given these characteristics you should be able to decide. Since there can be only one "France" and it doesn't change over time, it's probably a value object - unless your app needs to track more about a country which may change over time.

Imagine:
You have another entity - Customer.
Customer entity references Country object.
You have 2 entity instances with filled Country objects with same value (i.e. "France")
You are deleting country object from first entity (or first entity object)
if you want country to be deleted for 2nd entity object too
=> Country is an entity object
if you vant country to be deleted only for 1st entity object
=> Country is a value object

Related

Is there a "uniqueID" type property for address book contacts?

I'm making a game involving the user's contacts, but need a way to uniquely identify each contact. This is because the user can easily change the name, phone number, or other property of a given contact. Is there a way to do this?
You can use ABRecordGetRecordID() to get the unique ID of a record. It returns an ABRecordID which is a typedef for int32_t.
ABRecordGetRecordID() is the API that you can use. However, apple documentation does states some noteworthy points about the ABRecordID returned by this API.
Every record in the Address Book database has a unique record identifier. This identifier always refers to the same record, unless that record is deleted or the data is reset. Record identifiers can be safely passed between threads. They are not guaranteed to remain the same across devices.
The suggested method as per apple guidelines is
The recommended way to keep a long-term reference to a particular record is to store the first and last name, or a hash of the first and last name, in addition to the identifier. When you look up a record by ID, compare the record’s name to your stored name. If they don’t match, use the stored name to find the record, and store the new ID for the record.
In my app, I am also checking for creation date of the contact since the name against the ABRecordID could have been changed by the user. Creation date of a contact DOES NOT change upon device reset.
Though I have pasted most of the content here, its always advised to read the documentation

How to determine number of children of a record?

Good afternoon everyone!
I'm studying NHibernate, and decided to make some changes. Among them, I noticed that some fields are unnecessary. So I bring my doubt:
I have a list, let's call it Class_List within each study class, I can have N students for each class. Within the list Class_List, I also have other properties as simple as the name of the class.
How I see it is unnecessary to store how many students I have in the database, I would, in a single query, how many records I have. This, using NHibernate.
Is this possible? How?
Best regards,
Gustavo.
Edit: I've forgot to say one thing... I want to return this number of record, as a column. But this column is not mapped in my .hbm.xml file.
If students are mapped as a collection on Class, you can try using something like this:
var numberOfStudents = session.CreateCriteria<Class>()
.Add(Restrictions.IdEq(1))
.CreateCriteria("_students", "students")
.SetProjection(Projections.RowCount())
.UniqueResult<Int32>();
Where '1' is the id of the class (you can use other property) and '_students' is the name of the students collection.

Update an entity inside an aggregate

I was reading a similar question on SO: How update an entity inside Aggregate, but I'm still not sure how a user interface should interact with entities inside an aggregate.
Let's say I have a User, with a bunch of Addresses. User is the aggregate root, while Address only exists within the aggregate.
On a web inteface, a user can edit his addresses. Basically, what happens is:
The user sees a list of addresses on its web interface
He clicks on an address, and gets redirected to this page: edit-address?user=1&address=2
On this page, he gets a form where he can modify this address.
I we decided to bypass the aggregate root, this would be straightforward:
We would directly load the Address with its Id
We would update it, then save it
Because we want to do it the DDD way, we have different solutions:
Either we ask the User to get this Address by Id:
address = user.getAddress(id);
address.setPostCode("12345");
address.setCity("New York");
em.persist(user);
The problem with this approach is, IMO, that the aggregate root still doesn't have much more control over what's done with the address. It just returns a reference to it, so that's not much different from bypassing the aggregate.
Or we tell the aggregate to update an existing address:
user.updateAddress(id, "12345", "New York");
em.persist(user);
Now the aggregate has control over what's done with this address, and can take any necessary action that goes with updating an address.
Or we treat the Address as a value object, and we don't update our Address, but rather delete it and recreate it:
user.removeAddress(id);
address = new Address();
address.setPostCode("12345");
address.setCity("New York");
user.addAddress(address);
em.persist(user);
This last solution looks elegant, but means that an Address cannot be an Entity. Then, what if it needs to be treated as an entity, for example because another business object within the aggregate has a reference to it?
I'm pretty sure I'm missing something here to correctly understand the aggregate concept and how it's used in real life examples, so please don't hesitate to give your comments!
No, you're not missing anything - in most cases the best option would be number 2 (although I'd call that method changeAddress instead of updateAdress - update seems so not-DDD) and that's regardless whether an address is an Entity or Value Object. With Ubiquitous Language you'd rather say that User changed his address, so that's exactly how you should model it - it's the changeAddress method that gets to decide whether update properties (if Address is an Entity) or assign completely new object (when it's VO).
The following sample code assumes the most common scenario - Address as VO:
public void ChangeAddress(AddressParams addressParams)
{
// here we might include some validation
address = new Address(addressParams);
// here we might include additional actions related with changing address
// for example marking user as required to confirm address before
// next billing
}
What is important in this sample, is that once Address is created, it is considered valid - there can be no invalid Address object in your aggregate. Bare in mind however, that whether you should follow this sample or not depends on your actual domain - there's no one path to follow. This one is the most common one though.
And yes, you should always perform operations on your entities by traversing through aggregate root - the reason for this was given in many answers on SO (for example in this Basic Aggregate Question).
Whether something is an entity or VO depends on the requirements and your domain. Most of the time address is just a Value Object, because there's no difference between two addresses with the same values and addresses tend to not change during their lifetime. But again, that's most of the time and depends on domain you're modeling.
Another example - for most of the domains a Money would be a Value Object - 10$ is 10$, it has no identity besides amount. However if you'd model a domain that deals with money on a level of bills, each bill would have its own identity (expressed with a unique number of some sort) thus it would be an Entity.

How to name my enum elements?

I have a problem naming the elements in my application's data model.
In the application, the user has the possibility to create his own metamodel. He does so by creating entity types and a type defines which properties an entity has. However, there are three kinds of entity types:
There is always exactly one instance of the type.
For instance, I want to model the company I am working for. It has a name, a share price and a number of employees. These values change over time, but there is always exactly one company.
There are different instances of the type, each is unique.
Example: Cities. A city has a name and a population count, there are different cities and each city exists exactly once.
Each instance of the type defines multiple entities.
Example: Cars. A car has a color and a manufacturer. But there is not only one red mercedes. And even though they are similar, red mercedes #1 is different from red mercedes #2.
So lets say you are a user of this tool and you understood the concept of these three flavors. You want to create a new entity type and are prompted to choose between option 1, 2 and 3. How would you name these options?
Edit:
Documentation and help is available to the user. Also the user can be expecteted to have a technical/programming background, so understanding these three concepts should be no problem.
First of all let me make sure I understand the problem,
Here's what you have (correct me if I'm wrong):
#of instances , is/are Unique
(1,true)
(n,true)
(n,false)
If so,
for #of instances I would use single \ plural
for is\are unique (\ not unique) I would use unique \ ununique.
so you'll get:
singleUnique
pluralUnique
pluralUnunique
That's the best I could think of.. I don't know exactly who are your users and what is the environment, But if you have an option of adding tips (or documentation) that should be used for sure.

Mapping lookup table to class

I have a reference/lookup table whose main purpose is to provide the user with a list of existing options. The user will also have the ability to enter new items into the list. How would you map this in NHibernate?
For example, say I have an Address class with a City field. The database has an Address table and a City lookup table. (I can define the relationships however I want at this point.) When editing the address:
The user can select any available City, or can enter a new City.
A new city entered must be added to the lookup table.
Editing an Address instance's city should either change the reference - if the edited city also exists in the DB - or create a new City entry by that name and refer to it. (If I edit "Chicago" to "New York", I don't want all addresses in Chicago to change to New York; just the one I'm looking at.)
I've been scouring NHib docs, and I'm not at all sure what approach I should take.
EDIT:
Part of my issue stems from the fact that I'm trying to avoid creating a "City" class with a single property - I'd just like Address.City to be a string in the domain model. This may be unwise, I don't know.
So you have addresses and you want a distinct list of cities. You'll either need to do the "distinct" operation in your code or in the database. Doing it in code implies a City class mapped onto your City table - I can't see how you can avoid it.
If the "distinct" operation is done it the database, you'll need write sprocs to insert and update an Address. These sprocs would then contain the logic of "use the City if it's in the table, otherwise create a new one".
Personally I'm not in favour of sprocs if they can be avoided and so I'd recommend that you create a City class and map it with a on your Address class.