Hello Tauren,
sorry for not responding some time. I was away over the weekend and
had a busy start into the week.
> Perhaps you could explain what you mean by being too close to the
> physical design? These are my (simplified) Hibernate classes,
> annotated with @Entity. They are what ultimately gets stored in the
> database, each one having their own table. Plus there are additional
> relationship tables created by Hibernate. So yes, I guess they are the
> physical design. But I designed them like this since because they have
> the fields and relationships that my business logic needs.
Well, maybe I am a little bit picky or exaggerate about this. I am
currently reading a lot about refactoring code to make it more
maintainable and reduce impact of changes etc. So maybe it's just my
current mind set, that wants to remove the last one or two bits here.
I think the classes do look good. They really do. Don't worry too
much.
Now, physical design and domain design differ as that for your domain
you don't need to be able to get to the "nuts and bolts". For the
physical design it is important that we have IDs. For the application
this is not necessarily the case, because it deals with objects not
entities. Confused? I'll try to make it clear with code:
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
void someMethod() {
Person a = new Person("Grandpa", 82);
Person b = new Person("Grandpa", 82);
}
a and b are different objects although they are the same entity.
Entities are identified by their set of attributes. Objects are
identified by their very instance (or less philosophic: by their
memory address).
Of course you create the physical design according to your
application/business logic needs. (Coming from a DB background this is
what made it hard for me to get the whole point of the "physical vs.
business" at first, myself.) And this is where the lines start to get
blurry. If you wrote e.g. an book keeping application, every invoice
has an ID and you will sure want to use it in the business logic.
> Can you give an example of how they would look if they were NOT too
> close to the physical design? I'm not really using any DTOs, simply
> passing my hibernate entities from the service layer to the UI (which
> is done with Wicket). For my project, it seemed overkill to use DTOs,
> although there have been a couple instances where I wondered if my
> life would be easier if I had.
I could imagine that you might not need to use the ProjectParticipant
class in your business logic directly. I may be well off, because I
don't know your use cases, but this should make my point clear:
// code closely coupled to the physical design
void addAdminToProject() {
Project project = projectDAO.load(...);
Member member = memberDAO.load(...);
ProjectParticipant participant = new ProjectParticipant(project, member);
participant.setAdmin(true);
}
// code ignorant of the physical design
void addAdminToProject() {
Project project = projectDAO.load(...);
Member member = memberDAO.load(...);
project.addAdmin(member);
}
See, how in the second example the business logic doesn't care/know
that there is a ProjectParticipant class involved? In fact, the
Project and Member classes might not even be the same, because your
@Entity classes expose those physical design details.
...Excuse me? Oh, yes... yes, in fact I can be very picky about
details, why do you ask? :-)
> Also, are you suggesting that my Shiro realm code should be creating
> the permissions from data in DTOs? Or should it be using the hibernate
> entities directly, as I'm doing now?
The enitities are fine.
> Those example classes I provided had ben drastically simplified and
> left a lot of relationships out. I case it helps, below are more
> detailed hibernate entities with additional relationship information.
> Member and Role is the same as before:
I understand that you simplified them. Still they reveal
implementation details. And you cannot guarantee that any calling code
does not use some of the exposed details. I.e. your business logic
usually doesn't bother about how/where you store stuff, so your
classes should hide that from your business logic.
[...snip...]
>> I think what you mean is what I tried to explain with the two parts
>> above. I am quite sure you're on the right track. You might want to
>> add an additional layer above those classes you presented earlier, to
>> remove the last bits of physical design that you don't need for your
>> business logic.
>
> Again, I'm unclear what you mean with the additional layer above my
> classes, "to remove the last bits of physical design". Could you
> explain, or show a simple example (doesn't have to be my model if
> something else is easier to illustrate)?
The additional layer is the one that I used in the "loosely coupled"
code example above. So, you might have a
com.example.petstore.entities.Person class but your application logic
would rather use the com.example.petstore.domain.Person class instead.
I am no DDD guru, but as far as I understood your application domain
usually has only very few domain classes. By the way, there is an
interesting talk on DDD I watched lately:
http://www.infoq.com/presentations/rebuild-guardian-ddd-wills
> I'm certainly on track now, so feel free to drop things now if you
> don't have time to respond. If you do have time, I would appreciate
> some more clarification on your references to further abstraction from
> the physical design.
I hope I could communicate my thoughts properly. If you have any
questions, just ask. It will take some time for me to answer as I am
quite busy right now, but that should not stop you from asking. :-)
Cheers,
DJ