Hi Rich,
I only discussed Ratings in my previous message. Yes, a User should have
a collection of Songs, according to your requirement. It is important,
when working with a database back-end, to analyse the architecture of the
database as a database, and your business objects as business objects. A
database has relationships for the purpose of normalization, so that data
doesn't need to be stored redundantly. A set of business classes, on the
other hand, exists to process and manipulate data, and to enforce
business rules. So, you have to think differently when designing one or
the other. The database is just a storage mechanism, while the business
classes represent process that uses the data. In many cases, business
architecture and database architecture are similar, but one does not
dictate the structure of the other.
If we think of Users, Songs, and Ratings as business entities rather than
database (table) entitites , we can define them in terms of what they do.
A Song is a commodity, something used by Users. A Rating or a collection
of Ratings is part of the Song, or belongs to a Song. A User is a
consumer of Songs. So, a User will perhaps have a Collection of Songs,
but the Collection is not redundant. The Songs are commonly used by many
Users, a pool, if you will, or a global Collection. Each User may have
Songs in his/her Collection that are also used by other Users.
Now, the chain of dependency in this case runs in one direction only:
Users have Songs, which have Ratings. While Songs may be shared, Ratings
are not Shared. Each individual Rating is wholly owned by the song it was
created to rate. Furthermore, we need to think about the purpose of
Users, Songs, and Ratings. A User is a multi-purpose entity which
provides an interface for a person to interact with the application,
interact with other Users (perhaps), and interact with other business
entities in the application. A Song is a commodity that is employed by
Users. A User is active, while a Song is passive. A Rating is a commodity
that is employed by Users as well, but it is tied to a single Song. It is
also passive.
The real "trick" here is how the passive Songs can be collected
separately into each User's Songs collection. But if they are in a pool,
and each User has a Collection of references to Songs in the pool, there
is still only one instance of each Song. The Collection is a Collection
of references to Songs, not copies of Songs. Since a class is a reference
type, the pool is actually a Collection of references as well, but its
purpose is to collect all Songs into a single Collection. When a user
adds a Song to his/her Collection, he/she is simply adding another
reference, not adding a Song to anything. Similarly, when the User
removes a Song from his/her Collection, he/she is not deleting the Song,
but removing the reference to the song from the Collection of references.
When a Song instance is created, for example, by a User uploading it, it
is added to the pool. It is the pool that is used to manage the actual
Songs, not the Users who consume them. Again, when it is removed or
deleted, it is deleted from the pool.
A Rating, on the other hand, is a single instance that belongs to a Song,
and is a member of the Song's Ratings Collection. But since the purpose
of the Rating is statistical, and used for the most part in simply
getting the Rating Score for a Song, rather than a handle to a User, it
isn't necessary to add a Collection of User references to the Ratings
Collection, although it could be done.
--
HTH,
Kevin Spencer
Microsoft MVP
Printing Components, Email Components,
FTP Client Classes, Enhanced Data Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net
RichB said:
Thanks, Your statement that a song has ratings makes sense, though I am
not sure if I just include user ids how I would display (e.g.) the user
name with each rating. Why not have the relationship that Song has many
Ratings, and rating has a User as then if I needed to include anoth user
attribute in my presentation, (e.g.)the user postcode, I would not need
to make a change to my rating class, just use the existing postcode from
the user class?
From this model however I can get Songs, their Ratings and the
corresponding User (note there can only be one user per rating as aswell
as score there is revew text).
But there is no way to get Users and their corresponding Songs. In my
mind I can only navigate down the class structure Song.Rating[x].User
not start from User and navigate back to the corresponding Songs without
complex looping through all of the Songs. I may be missing something
fundamental here, but I would have thought that this was a pretty common
problem.
Thanks, Richard
Your Song and User classes are just fine. However, your Rating class is
the problem. A Rating doesn't have a song; a song has a rating, or it
may have many ratings. Again, a Rating doesn't have a User, and neither
does a User have a rating. A rating may have a reference to a number of
users, but these are not users; they might only be User IDs from the
database, so that you can fetch information for any user if your
requirements dictate that. The other part of the rating is not a song,
but a score. Does that help?
--
HTH,
Kevin Spencer
Microsoft MVP
Printing Components, Email Components,
FTP Client Classes, Enhanced Data Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net
I am trying to build a rating engine for a number of users for a list
of
songs. I havea database design with a user table and a song table and
a link
table such that each user can rate many songs and each song can be
rated by
many users.
However I am a little stuck on the class design. I hope that this is
the
correct place to post such a question and that someone can help with
an
answer.
Simply put each rating has a user and a song, which leads me to three
classes
class Rating
{
Song song;
User user;
}
class Song{}
class User{}
This is the point at which I am slightly confused if I have a rating
object
then I can refer to the song by rating.song and the same for the user.
However If I just want to list all of the ratings for a song, then I
really
need the Song object to be composed of a list of ratings in something
of a
circular relationship.
Whilst this seems to be supported in c#, it does seem to be risky if a
rating has a song, but the song does not include that rating within
the list
of ratings.
Is there another way to build these classes, or is the only way to
describe
the relationship between a rating, a user and a song and between a
song or
user and it's ratings?
I would be grateful for any assistance. I am very confused about this,
so
apologies if my question is confusing.
Richard