bojanv55 bojanv55 -4 years ago 64
Java Question

Can Entity be identified by all of its properties?

Question is - can Entity be defined by all of it's properties or only by it's Id.

This is the example:

class Wallet{
int id;

Map<BillType, Bill> bills; //can have only 1 bill per bill type

void addBill(BillType billType, Bill bill){
this.bills.put(billType, bill);
}
}

//this is probably an Entity, since it is mutable, but it has no global Id (only local bound to wallet)
//and equality is based on all of the properties
class Bill{
BillType billType;
Map<TypeOfBillSide, SideOfBill> billSides; //can have only front or back

Bill(BillType billType){
this.billType = billType;
}

void drawWithPenOnBillSide(TypeOfBillSide typeOfBillSide, String drawing){
this.billSides.get(typeOfBillSide).drawWithPenOnBillSide(drawing);
}

void burn(){
System.out.println("I burned this bill");
}
}

//this is probably an Entity, since it is mutable, but it has no global Id (only local bound to Bill)
//and equality is based on all of the properties
class SideOfBill{
TypeOfBillSide typeOfBillSide;
String drawing;

public SideOfBill(TypeOfBillSide typeOfBillSide) {
this.typeOfBillSide = typeOfBillSide;
}

void drawWithPenOnBillSide(String drawing){
this.drawing = drawing;
System.out.println("I draw on this side " + this.drawing);
}
}

enum BillType{
DOLLAR_10,
DOLLAR_20,
DOLLAR_50;
}

enum TypeOfBillSide{
FRONT_SIDE,
BACK_SIDE
}


Here I have globally unique Wallet - that is Aggregate Root. It has Bills which I think are entities in this case (since I can alter the state of the Bill and it is still that bill that is in the wallet). State can be altered by drawing some string on any of the sides of the bill (SideOfBill - which is also an entity in this case).

Bill by itself has meaning only as part of wallet, and also in wallet I can have only 1 kind of bill (I cannot have 2 bills with 10$ eg. only one).

If I treat this as Value object, and make it immutable, then each time I draw something on the Bill, I have to make new bill - which in this case is a bit strange and also hard to do in code.

If I treat this as the entity that is globally unique, I would have to have id for Bill that is actually composite from [Wallet.Id & Bill.billType]. But Wallet.id does not fits naturally to Bill class in this case.

The most natural thing is that I treat Bill as Entity and have equals method that tests all of the Bill properties (at the same time all properties of the SideOfBill since it is contained in Bill class).

Is this common case to have?

Answer Source

Although it is not common practice, Value Objects (VO) surely can be mutables (e.g. for performance reasons). However, you need to make sure that mutable VOs aren't shared.

Still, the need for a mutable VO is perhaps a strong indicator that the concept you are trying to model is in fact an entity. A good question to ask yourself is whether or not you are interested about the lifecycle of this instance.

For example, in your case would it be important to keep the history of changes that were made on a bill? If it is then a bill should be modeled as an entity.

If I treat this as the entity that is globally unique, I would have to have id for Bill that is actually composite from [Wallet.Id & Bill.billType]. But Wallet.id does not fits naturally to Bill class in this case.

Do not forget that from the domain model perspective, entities must only be uniquely identified within their Aggregate Root (AR). That means billType could serve as a bill's ID within a wallet.

Also note that the bill could have a surrogate identity from the database perspective or a (walletId, billType) composite ID if needed.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download