views:

164

answers:

4

Hi SO.

I am learning a lot about design patterns when I am building my own system for my projects. And I want to ask you about a design question that I can't find an answer to.

Currently I am building a little Chat-server using sockets, with multiple Clients. Right now I have three classes:

  1. Person-class which holds information like nick, age and a Room-object.
  2. Room-class which holds information like room-name, topic and a list of Persons currently in that room.
  3. Hotel-class which have a list of Persons and a list of Rooms on the server.

I have made a diagram to illustrate it (Sorry for the big size!): http://i.imgur.com/Kpq6V.png

I have a list of persons on the server in the Hotel-class because it would be nice to keep track of how many there are online right now (Without having to iterate through all of the rooms). The persons live in the Hotel-class because I would like to be able to search for a specific Person without searching the rooms.

Is this bad design? Is there another way of achieve it?

Thanks.

+7  A: 

I don't like it. A hotel contains rooms, and rooms contain people. People don't contain rooms, they belong to them.

You don't necessarily have to iterate to get your guest count. You could just keep a running count ($Hotel->total_guests) and modify it as it changes.

Syntax Error
I understand what you say, that there is a flaw in my logic, thanks for pointing that out! However my thinking was that a HashMap containing the username, and the Person-object would be way faster for searching for a user than iterating through Rooms.
Kasper Grubbe
I thoroughly appreciate your lust for milliseconds, as I share that passion - but awesome OOP is about faster/cleaner reading and writing of code, not faster execution time. I would suggest you try it both ways and time it - the differences will probably not be as big as you think. (If you do this please post your results for us!)
Syntax Error
You got me! That comment about lust for milliseconds is spot on. You have given me something to think about, thanks :)
Kasper Grubbe
+1 for "but awesome OOP is about faster/cleaner reading and writing of code, not faster execution time."
Uncle
+1  A: 

In a larger system, it would be bad, but since from what I understand of your applications, these three classes are only use together, it's not much of a problem. Just make sure to name the person's member variables in a way that indicates that it contains a reference to a room, rather than an instance.

Also, unless it's for performance reasons (e.g. you will have a huge number of rooms), it would probably be cleaner to make a property or getter that would iterate over the rooms and collect the persons, rather than caching them in the hotel.

Max Shawabkeh
For the record, I agree that caching them as a property of hotel is probably not the best way to go about it. Personally I would iterate too ;)
Syntax Error
What would you name the member variables in Person, so it would be more like a reference?Let's say that I have a huge amount of users, and that I need to search for a single user. What would be the best way? I know that I keep redundant information in references. These classes are only used together (There are a couple of more, but not many).
Kasper Grubbe
+1  A: 

The mutual dependency problem among the classes, strictly speaking, can be solved by using interfaces (abstract classes, if your language is e.g. C++ or Python) IRoom and IPerson; in pseudocode

interface IPerson
    IRoom getRoom()
    // etc

interface IRoom
    iter<IPerson> iterPerson()
    // etc

this makes only the interfaces mutually dependent on each other -- the actual implementations of the interfaces need only depend on the interfaces.

This also gives you plenty of leeway in terms of implementation, if you want avoid circular reference loops (which can be a bother e.g. in CPython by slowing down garbage collections) -- you could use weak references, an underlying relational database with a typical "one to many relationship" table, etc, etc. And for the first simple prototype you can use what's simplest in your chosen language (probably simple, and alas necessarily circular, references [[pointers, in C++]] with a Person referring to a Room and a Room to a list<Person>).

Alex Martelli
I see "mutual dependency" is the word that I was looking for. For the record I am writing this in Java. The interface approach seems interesting, but doesn't make the solution much more different, but I get your point. Thank you, for your comment.
Kasper Grubbe
@Kasper, point is, there is no real problem with having dependencies on _interfaces_ (including mutual ones) -- it's mostly dependencies on _concrete_ software that you really want to avoid (e.g. in case of "loops"). The freedom to start with a quick and dirty implementation and switch to a sounder one later also speeds software prototyping and iteration in its evolution and maintenance.
Alex Martelli
A: 

Mutual dependency is not bad in its own right. Sometimes the data usage requires it.

I think about it in a different way. It'll be easier to maintain code that has fewer relationships in general-- mutual dependency or not. Just keep it as simple as possible. The only additionally trickiness with your situation is sometimes there's a check and egg problem, during create and delete sequences. You've got more links to bookkeep.

If you're asking about whether you need a list of persons on a hotel in this case, I think there are two answers. I'd start out by having your objects (in memory) supplying these relationships, but you do NOT need an additional join table between people and hotels in the database. If you are using Hibernate, it will automatically generate an efficient join for your if you ask it for the people in a hotel (it will join hotels on rooms.hotel_id for you).

ndp