Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Basic OO question

Status
Not open for further replies.

Sooty70

Programmer
Oct 14, 2004
16
US
Hi Folks,

Most of my background has been working with databases so I tend to think about problems in terms of data. I know that objects can contain data but thinking of them as simply data holders can be a bad thing. I've been trying to correct myself in the way that I think of objects. I've coded Java for a couple of years now but I still I may be thinking subconsciously of groups of objects that hold data. Anyway, that's just a little background to see where I am coming from.

What I am looking for is a little guidance with a very simple problem. I have two classes in a system - Player and Competition. The Player class holds basic person information such as login, password (security is not an issue), name, etc. The Competition class holds information such as name, year, administrator, etc. A Player can register to particpate in many Competitions but they will usually just be in one. The application is a web app that uses a fair bit of JSP.

The scenario that I am thinking of is this. When the Player logs into the system and they want to view their Competition details, they need to select the Competition from a dropdown box. This means that the application has to know what Competition names to populate the drop down with. Since the application already has awareness of who the Player is it sounds to me as though the Player instance should be responsible for maintaining the Competition information. Does that sound right or are there things I am not thinking about?

I'm wondering which of the three methods is best:

[1] Each instance of the Player class contains a collection (e.g. a Vector) of registered Competitions.
[2] Each instance of the Competition has a reference to the associated Player instance.
[3] Have a method in the Player class that reads the database and retrieves all the Competitions on the fly and returns them in a Vector.

My thoughts...
[1] sounds like the best idea.
[2] I don't think I should be creating an object for every Competition since the competition information will be the same for every player. I am thinking that Competition data should exist in an application scope Vector that could be updated on the fly if any new Competitions were added (a rarity in itself, usually just once a year).
[3] this sounds like the process necessary for idea [1] except it would be performed every time the Player accesses a certain page. Sounds much better to read the information once, store it in the Player instance and be done with further database transactions.

I think I have it clear in my head but I just don't know if it is clear AND correct. :)

I hope I provided enough information. It is purposefully vague and I am only talking about a small piece of the application. I can provide any other information should I not have done a good job of asking my question.

Cheers, Max
 
To clarify a little on the above let me use an example.

Here are some Competitions as they are stored in the database:
Comp02, 1, 2002, [NULL], 0
Comp03, 1, 2003, [NULL], 0
Comp04, 1, 2004, [NULL], 1

The fields are :
competition name
administrator Id
year
password
isCurrent (boolean flag)

This Competition information is the same for every single Player so it doesn't appear to make sense to add a new member e.g. playerId, and then create an instance Competition for every single Player / Competition combination.

I am weighing down heavily on the idea of putting the responsibility for the Competition "management" in the Player class but I just want to see what others think. :)

Thanks, Max
 
Stop thinking about the data, and instead think about the methods you will need to implement to make the system work.[ol][li]Is an Administrator a Player? Or another object? In which case, Player and Administrator are roles that can be played by a Person. Possibly simultaneously, and in different Competitions. So now we can split the responsibilities up, and give Administrator responsibility for creating and managing competitions.[/li][li]Once Administrator has registered a player for a competition, we can ask a competition for a list of its players, or ask a player for a list of associated competitions.[/li][li]You certainly don't want an instance of Competition for each combination, but on your database you probably need a table to implement a many-to-many relationship between the two. You don't have to map your objects 1:1 with your tables, so you don't need necessarily need a PlayerCompetition object to do the mapping. You can join the players, playerCompetition, and competition tables to instantiate a player object with a collection of associated active competetions. And a similar query when you instantiate a competition, to give it a collection of players.[/li][/ol]Hope this helps a bit...
 
Thanks Steve, that helps.

[1] The Administrator is a Player and you are correct, sometimes both roles can be played simultaneously. The difference between an Administrator and a Player is just access to certain pages and commands.

[2] People register using a self-register page. Registration is open to everyone unless there is a password associated with the Competition in which case the person must know this password (typically e-mailed out to a list of people). What interests me most about your statements above is this, "we can ask a competition for a list of its players". What would be the mechanism for asking this question? Are you suggesting that I have an instance of Competition for each valid Competition (isCurrent=1 in the Db) that contains a collection (e.g. a Vector) of all the Players that are registered? That way I could have something like this:

public class Competition {
private Vector mPlayers;

public Competition() {}

public void loadPlayers() {
// implementation to load registered Players from Db
}

public Vector getPlayers() {
return mPlayers;
}
}

I can then do something similar for the Players with respect to the list of Competitions they are registered to play.

[3] agreed

I'll read over your reply again a few times to make sure I understand you correctly. :)

Cheers, Max
 
You can join the players, playerCompetition, and competition tables to instantiate a player object with a collection of associated active competetions. And a similar query when you instantiate a competition, to give it a collection of players."

This is the key piece right here. I understand what you are saying.

If I may ask another question. Let's assume that a player logs in but they may not necessarily be logging in to review the competitions they are registered in e.g. say they just want to update their profile. Would it be a good idea to only load the Competition data when it's first requested to speedup the instantiation of the Player object? I believe I would just create the Player object with a null Vector and when a request comes in for a list of Competitions the database calls could be made a that time? For example:

Player.java
public Vector getCompetitions() {
if ( mComps == null ) {
mComps = loadComps();
}

returm mComps;
}

void loadComps() {
// implementation to load mComps with competitions from Db
}

I think this "gradual recognition" process has an official name but I can't think of it just now. :)

Cheers, Max
 
I wish I could edit my posts. :)

I understand the above code is flawed. The return type for loadComps is defined as void and it should be Vector i.e.

Vector loadComps()

Anyway, the code is piecemeal and only to help describe the process as opposed to being actual, working code.

Cheers, Max
 
The process you describe is generally called 'lazy loading'. You don't go to the database to get the collection unless the caller asks for it. Checking for null is one way to do it, an alternative is to use a separate private boolean, which you set true when you have fetched the collection. Then, if they aren't registered for any competitions, you know they don't have any and still only have to do it once.

Also, I understand your worries about performance and how many times you hit the database, but most databases these days are pretty slick at buffering queries. Generally speaking you should code it as simply as possible (then there's less to go wrong), and then tune it up if it doesn't perform. You don't say how many hits per second/minute/hour you are expecting, but I'm guessing it won't be huge...
 
Thanks again Steve. Performance is never going to be a problem on this site even if I went to the database every single time, it's not very heavily used. I guess I could measure it in hits / week. :)
 
There is a fundamental disjoint between Objects and Tables, and it's where many object-relational mapper tools fall down. They either generate objects from tables or vice versa.

Design your system using objects. Objects are the nouns in your system, like Person, Administrator, Player, and Competition. If you use UML, sequence diagrams are a good way to show the object interactions (method calls) in each use case. The method calls are the verbs - things you can do to each object. The data items and collections you need will become apparent when you try to use the methods - what needs to be passed on a call, what an object needs to 'know' about itself etc.

Once you have a set of objects that work together on paper, come up with a table design that supports it. It doesn't have to map exactly, and you might even use views or stored procedures to support some of your methods.

Then start coding it...
 
Good tips. The reason I am even here posting these questions is because I read UML Distilled Second Edition and I wanted to make myself a "better" coder. I've been in QA for the last 3 years and I was in development / DBA work before that. I'm trying to get back on the development track but it proves difficult when the last 3 years have been non-development. I'm kinda trying to re-invent myself again. Anyway, just thought I would pop that in there. :)
 
Hi,
this is an interesting post. You might have your answer already but don't mind me throwing in my advice.

Seems like you are misunderstanding seperations of concerns, distribute responsibility in a way that increases cohesion in a class.

You originalling wrote:
1. "This means that the application has to know what Competition names to populate the drop down with."
This can be easily solved with the concept of a Repository:

pseudo:
List aList = CompetitionRepository.FindAllByPlayerId(10393);

2. "Since the application already has awareness of who the Player is it sounds to me as though the Player instance should be responsible for maintaining the Competition information."

When you say maintaining, are you referring to basic CRUD (Create, Read, Update, Delete) work? If so, Repositories solve these as well.

Sure there is a relationship between Players and Competitions but follow a Single Responsibility Principal. Let Players do player kind of things and let competitions do competition kind of things. Let each class have a single reason to change.

If you need to establish a one-to-many relationship at runtime, simple delegate to a repository to satisfy that:

aPlayer.Competitions.Add(aRepository.FindById(xxx));




 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top