Fwd: DDD-principer

1 view
Skip to first unread message

Anders Asplund

unread,
Nov 24, 2010, 4:20:45 PM11/24/10
to oppna-program...@googlegroups.com
> Detta bör väl vara grundprincipen och bör förklaras tydligare i
> Javadocen.
Bra kommentar, tar på mig att fixa det.

> Skulle AbstractEntity kanske implementera getId() och ta
> ett ID i sin constructor?
Funderade på något liknande men kan tycka att en implementation blir ganska otydlig om vad som är dess id:

public class Person extends AbstractEntity<PersonalNumber> {
public Person(PersonalNumber pn) {
super(pn);
}
}

men det kanske inte är skäl nog...?

...och vill man generera sitt id på så skulle följande implementation kunna exemplifiera det så här:

public class TestEntity extends AbstractEntity<UUID> {
private TestEntity(UUID id) {
super(id);
}
public static TestEntity newInstance() {
return new TestEntity(UUID.randomUUID());
}
}

> Men ni tycker alltså att implementationen av equals är bra, där equals
> returnerar true for id = null på båda objekten?
Detta borde tämligen bara bli ett problem om man låter databasen generera entitetens id genom att likställa PK och ID. I princip tycker jag inte man borde göra detta, dock förstår jag att det är väldigt smidigt.

>
> Ser i så fall hellre att man tar bort final från equals() och hashCode().
Håller inte med. Per definition(och enl. javadoc) så identifieras en entitet av sitt id, detta kan inte garanteras om man släpper på equals.

En av tankarna från början med ramverket var att få hjälp med boilerplate för ddd-driven design på datalagret. Jag kanske är lite fundamentatlistisk men för mig är vikitgt att hålla på dessa principer då jag tror att det i slutändan resulterar i bättre kod.

//Anders

Niklas Gustavsson

unread,
Nov 24, 2010, 4:41:59 PM11/24/10
to oppna-program...@googlegroups.com
2010/11/24 Anders Asplund <aasp...@gmail.com>:

>> Skulle AbstractEntity kanske implementera getId() och ta
>> ett ID i sin constructor?
> Funderade på något liknande men kan tycka att en implementation blir ganska otydlig om vad som är dess id:
>
> public class Person extends AbstractEntity<PersonalNumber> {
>   public Person(PersonalNumber pn) {
>       super(pn);
>   }
> }
>
> men det kanske inte är skäl nog...?

Problemet, efter att ha tänkt lite mer på detta är hur man får det att
lira med JPA eftersom den kräver en default cstr och sen lite magiskt
petar in värdena. Det blir då svårt att på ett vettigt sätt sätta id
fältet.

>> Men ni tycker alltså att implementationen av equals är bra, där equals
>> returnerar true for id = null på båda objekten?
> Detta borde tämligen bara bli ett problem om man låter databasen generera entitetens id genom att likställa PK och ID. I princip tycker jag inte man borde göra detta, dock förstår jag att det är väldigt smidigt.

Håller också med om att detta snarast är att betrakta som en bugg i
entiteten. En bugg som jag för övrigt har i *alla* mina entiteter (men
dock avser fixa).

>> Ser i så fall hellre att man tar bort final från equals() och hashCode().
> Håller inte med. Per definition(och enl. javadoc) så identifieras en entitet av sitt id, detta kan inte garanteras om man släpper på equals.

Men vem är det som ska garantera det? Ser inte att ramverket i varje
situation ska vara garanten. Att ramverket erbjuder en vettig default
tycker jag är bra, men jag är inte lika säker på att aldrig ska
tilllåta en subklass göra det själv.

/niklas

Annica Sunnman

unread,
Nov 25, 2010, 1:43:43 AM11/25/10
to oppna-program-dao-framework
Dessutom i AbstractEntity så återfinns metoden:

/**
* {@inheritDoc}
*/
@Transactional(propagation = Propagation.REQUIRED)
public T store(T entity) {
if (entity.getId() == null || entityManager.find(type,
entity.getId()) == null) {
persist(entity);
return entity;
} else {
return entityManager.merge(entity);
}
}

Vilket om nu DDD principerna skall följas så borde följaktigen inte
denna metoden existera?

Man borde ju kunna få garantera själv att ett objekt skall insertas
med antingen ett id eller en pk genererad från databasen. Hade inte
förstått tidigare att detta inte var fallet men det ger sig väl i
Javadocen om den uppdateras.

Att två null värden returnerar true på equals tycker jag fortfarande
är ett grundproblem. Antingen borde inte null värden tillåtas alls för
att undvika att man hamnar i ett läge där objecten anses lika även om
de inte är det samt att man kan får välja om man nu vill generera id
från databasen.

/Annica

Annica Sunnman

unread,
Nov 25, 2010, 1:54:15 AM11/25/10
to oppna-program-dao-framework
Är inte sämre att man kan erkänna att jag hade ett fel... Det hade
smygit sig in en liten long istället för Long - så mitt ursprungliga
problem löste sig.

Men tycker fortfarande att man skall kunna göra override på equals vid
behov. Genererade nycklar borde tillåtas.

Anders Asplund

unread,
Nov 25, 2010, 3:34:55 AM11/25/10
to oppna-program...@googlegroups.com
VAB:ar i dag men har lite idéer som jag vill prova när jag får tid(förmodligen först i kväll) återkommer med kommentarer då.

Niklas Gustavsson

unread,
Nov 25, 2010, 7:18:43 AM11/25/10
to oppna-program...@googlegroups.com
2010/11/25 Annica Sunnman <annica....@gmail.com>:

> Att två null värden returnerar true  på equals tycker jag fortfarande
> är ett grundproblem.

För att förtydliga så håller jag med, två entiteter med ID null ska
inte ge true från equals.

/niklas

Anders Asplund

unread,
Nov 25, 2010, 7:39:59 AM11/25/10
to oppna-program...@googlegroups.com
> Att två null värden returnerar true på equals tycker jag fortfarande
> är ett grundproblem.
Jag tycker det kan vara motiverat att delegera till super i dessa fall. Att släppa på final är jag däremot inte övertygad om, men jag kan ju bli övertygad med rätt argument ;-)


//Anders

David Rosell

unread,
Nov 26, 2010, 12:53:00 PM11/26/10
to oppna-program-dao-framework
On Nov 25, 1:39 pm, Anders Asplund <aaspl...@gmail.com> wrote:
> > Att två null värden returnerar true  på equals tycker jag fortfarande
> > är ett grundproblem.

hmm, jag tittade faktiskt efter i koden, två null id returnerar inte
true ;)

public final boolean equals(final Object other) {
if (other == null) {
return false;
}
if (other == this) {
return true;
}
if (getClass() != other.getClass()) {
return false;
}

@SuppressWarnings("unchecked")
T otherType = (T) other;

if (getId() == null || otherType.getId() == null) {
return false;
}

return new EqualsBuilder().append(otherType.getId(),
getId()).isEquals();
}

(och hashCode delegerar till object.hashCode om entiteten inte hunnit
få sitt id.)

Men frågan är kanske om man skall plocka bort detta beteende...

Anders Asplund

unread,
Nov 28, 2010, 10:34:34 AM11/28/10
to oppna-program-dao-framework
> hmm, jag tittade faktiskt efter i koden, två null id returnerar inte
> true ;)
Helt riktigt David!
Hade faktiskt inte verifierat detta tidigare

> (och hashCode delegerar till object.hashCode om entiteten inte hunnit
> få sitt id.)
>
> Men frågan är kanske om man skall plocka bort detta beteende...
Vad gäller hashCode så behöver vi fundera lite över hur vi skall
hantera detta om vi tillåter null-id:n.
Enl. hashCode-kontraktet så skall det bl.a alltid generera samma
nummer oavsett när det körs ( http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode()
). Så är ju inte fallet nu...

//Anders

Anders Asplund

unread,
Nov 28, 2010, 12:57:09 PM11/28/10
to oppna-program-dao-framework
> Vad gäller hashCode så behöver vi fundera lite över hur vi skall
> hantera detta om vi tillåter null-id:n.
Bästa sättet blir nog att i javadocen trycka på vikten att förse
entiteten med ett ID redan när den föds. Det blir nog svårt att från
ramverket tvinga fram ett ID (Niklas hade ett förslag tidigare men som
visade sig svårt att implementera tillsammans med JPA). Om detta är ok
för er så fixar jag det.
Reply all
Reply to author
Forward
0 new messages