The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Breaking OO rules for query logic?

Hello all,
Ok, long-winded and contrived scenario to ask what's a pretty simple question.

Objects:
- Person
- Band
- BandMembership

Requirements:
1. People can be only in one band at a time (no side projects allowed)


Say we're using an OO mapper (but not one based on an ActiveRecord pattern -- so the domain objects know nothing of persistence). Now, I need to make a screen to allow new members to be added to a band. I need a list of people available to be added. This will be some kind of querying criteria -- in sql pseudo code:

select from people where id not in (select personid from bandmembership where bandmembership.isCurrent)

I feel like this "logic" should exist in the domain model somewhere. What if the criteria for band membership changes, and side projects are allowed? It just doesn't seem to be practical to put this in the domain model, though.

What do other people do in this situation? Is there some very obvious way I've just overlooked? Please help enlighten me.

Peter
PeterL Send private email
Friday, August 03, 2007
 
 
There doesn't seem to be a domain model, it's a simple CRUD app. So don't worry about it. That's one approach.
son of parnas
Friday, August 03, 2007
 
 
You could try to make a criteria object in the domain and pass it to the persistence layer, which would then own the job of getting the search done. Read up on Domain Specific Languages for neat ways of expressing rules. Here's a clumsy attempt off the top of my head ...

Criteria = new Criteria().equals("band", NONE).or().equals("membership", FLEXIBLE)
Stan James
Friday, August 03, 2007
 
 
In this case, we do not make the band membership "object" you have.  We treat that as a relational database implementation detail - just because you have a table does not mean you have an object.  In the object model, the bands contain collections of members.  The band is responsible for persisting itself and the collection relationship to the database properly in the band and membership tables.

In your case, however, I would not even have a membership table, since you are not allowing people to be members of more than one band, so (unless temporal changes are important), I would simply have the person have a foreign key column storing the ID of their band.
Cade Roux Send private email
Friday, August 03, 2007
 
 
Person is a "master" table - it contains last name, first name, city, etc.
Band is a "master" table - it contains name, genre, inception date, etc.
BandMembership is a linking table. it contains a band ID and a member ID.

With this model you can have any member be a member of any number of bands by making the key for the table be BandID + MemberID.

If you want to start out by restricting members to one band, simply reject any requests to add a second band membership for a member.  When the restriction is relaxed, just get rid of the rejection code.  Of course you may have to rewrite reports and other elements to accommodate the change in requirements ...

This is the way software evolves over time.  You start with an initial set of working rules and as your app gets into the marketplace and people use it they start pointing out the holes and missing things in the app.  That's why v2, v3 etc. exist.
Karl Perry Send private email
Saturday, August 04, 2007
 
 
son of parnas:
That example is not representative of the scope of the application or domain.

Stan James:
Thanks for the suggestion. I think this might be the way I go with this -- allow "querying" in the domain model in a
persistence-agnostic manner.

Cade:
The point of setting up the example this way was to show that temporal changes -are- important. I'm not worried just about who is a member of this band, but also who has -ever- been a member of this band. Like an employment history...

Karl:
See the point about the importance of "temporal" information. Also, I'm trying to avoid have to scan through every person in the system in memory to construct a list of "possibles". So I guess what I really need is a way to make that "query logic" part of the domain model in a safe way.


Thanks for the feedback, it's given me a lot to think about.

Monday, August 06, 2007
 
 
In the case of the temporal consistency, keep the membership table, you need to add effective dates to it and a constraint based on the effective dates.

I still would not have a first-class membership object in the domain object model, but instead put a criteria "knob" on the collection child object which indicates the effective date of the collection.  A collection object which has a non-current effective date cannot be altered by adds or removes (for obvious reasons).

The current collection should offer an add and remove, taking an effective date which is used to populate the effective dates in the membership records.

When you construct a band, you will not only need the ID but the effective date at which you want to look at the membership.  You can overload the constructor, so that passing no date is the same as passing the current date.

Right now, people are only allowed to be a member of one band, but if that changes, then the person would also need an effective date in their constructor.
Cade Roux Send private email
Tuesday, August 07, 2007
 
 
I would suggest picking up the book "Java Persistence With Hibernate".  You may not even be using Java or Hibernate, but its theoretical background information on OO design and the persistence of an OO domain model is quite useful.
DavidInTx Send private email
Tuesday, August 07, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz