Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Need Help with design of class hierarchy

124 views
Skip to first unread message

sdu...@gmail.com

unread,
Mar 11, 2015, 2:33:12 PM3/11/15
to


Hi, I am having a difficult time figuringout how I'm going to design my
base and derived classes for a specific project.

What I'm looking to do is come up with a design for an efficient OO class design
to represent songs in an Artists catalog. Songs at te lowest level. Then Discs
becasue each song is contained on a disc within a particular release by the
artist. And there are multiple releases. And multiple artists.

Here's a very simplified example of what I've been thinking of. Hopefully this
will be readable and understandable to everyone:


class Song // every song has it's own class
string &name; // full path to song on disk.
virtual GetRelease(); // With a pointer to any Song class, one
virtual GetArtist(); // could obtain the Disc, Release and
virtual GetFullPath(); / /Artist associated with that song.


class Disc : Song // Each Release has at least 1 disc
virtual int GetDiscNumber();


class Release : Song
virtual string& GetFullPath();
virtual string& GetRelease(); // Get name of the Release


class Artist : Release
virtual string& GetArtist();


With the above simplistic design, if you have pointer to a Song class, you can
get the Artist name and the name of the Disc, Release and Artist. What I don't
like about it though is that to represent an entire I would need name instances
of the Artist class. I would need an instance of the artist class for every song
on that particular Release. Then to represent the Artists entire music
collection, I would need an Artist class for every song in the artists catalog.
The same is true for all classes up the hierarchy. An artist has many releases

An alternative.

class Song
string &name;


class Disc
array<Song*> songs;


class Release
array<Disc*> discs;


class Artist
array<Release*> releases;


What I fdon't like about the above design is that there's not any OO'ness about
it. array's could be lists, doesn't matter. If I have a pointer to a Song class,
I don't have any oter information about the song. I can't get the Artist name,
the release it came from, etc ... But what's good about it, as compared to the
first example, is I only have 1 instance of the Artist class for each and every
artist.

Looking for suggestions on how one would go about designed a good class
hierarchy to represent the music of a particular recording artist.

Any suggestion greatly appreciated.


Scott


Victor Bazarov

unread,
Mar 11, 2015, 3:36:35 PM3/11/15
to
On 3/11/2015 2:32 PM, sdu...@gmail.com wrote:
> Hi, I am having a difficult time figuringout how I'm going to design my
> base and derived classes for a specific project.
>
> What I'm looking to do is come up with a design for an efficient OO class design
> to represent songs in an Artists catalog. Songs at te lowest level. Then Discs
> becasue each song is contained on a disc within a particular release by the
> artist. And there are multiple releases. And multiple artists.
>
> Here's a very simplified example of what I've been thinking of. Hopefully this
> will be readable and understandable to everyone:
>
>
> class Song // every song has it's own class
> string &name; // full path to song on disk.
> virtual GetRelease(); // With a pointer to any Song class, one

virtual WHAT GetRelease() ? What's the return type?

> virtual GetArtist(); // could obtain the Disc, Release and
> virtual GetFullPath(); / /Artist associated with that song.
>
>
> class Disc : Song // Each Release has at least 1 disc
> virtual int GetDiscNumber();

'Disc' derives from 'Song'? So a 'Disc' IS-A 'Song'? I am not sure I
actually agree. Shouldn't 'Disc' be actually a container of 'Songs'?
OK, here is a suggestion: start from the right end. What you need is a
system that *uses* your objects. From their *use* you can distill their
*interface*. Once you have the interface, the class design becomes a
walk in the park. So, start with describing how your objects are going
to be *used*.

And it doesn't really matter what language you are going to use to
implement your system. Don't try designing with any specific language
in mind. Forget 'virtual' or 'array<>' or "pointer to". Use
pseudo-code to describe the relationships. Translating your pseudo-code
into any language of your choice is not important to the design, really.
What if tomorrow you decide to make a prototype of your system in Python?

I probably didn't understand the entity relationships in your
explanation, so excuse my reaction. I hope you will see the problem
from my POV.

Good luck.

V
--
I do not respond to top-posted replies, please don't ask

Norbert_Paul

unread,
Mar 12, 2015, 3:37:30 PM3/12/15
to
sdu...@gmail.com wrote:
>
>
> Hi, I am having a difficult time figuringout how I'm going to design my
> base and derived classes for a specific project.
>
> What I'm looking to do is come up with a design for an efficient OO class design
> to represent songs in an Artists catalog. Songs at te lowest level. Then Discs
> becasue each song is contained on a disc within a particular release by the
> artist. And there are multiple releases. And multiple artists.

A song may be contained in more than one disk.
A disk may conatin more than one song.
Hence you have an n:m association.

> Here's a very simplified example of what I've been thinking of. Hopefully this
> will be readable and understandable to everyone:

It is.

> class Disc : Song // Each Release has at least 1 disc
> virtual int GetDiscNumber();

Your Model, however, states here that every Disk "isA" special kind of Song.
This is what class inheritance is good for.

> class Release : Song
> virtual string& GetFullPath();
> virtual string& GetRelease(); // Get name of the Release
>
>
> class Artist : Release
> virtual string& GetArtist();

Similar problem: Each artist "is a" specual kind of Release here.

> With the above simplistic design, if you have pointer to a Song class, you can
> get the Artist name and the name of the Disc, Release and Artist. What I don't
> like about it though is that to represent an entire I would need name instances
> of the Artist class. I would need an instance of the artist class for every song
> on that particular Release. Then to represent the Artists entire music
> collection, I would need an Artist class for every song in the artists catalog.
> The same is true for all classes up the hierarchy. An artist has many releases

Good. You are aware of the flaws of the above design.

> An alternative.
>
> class Song
> string &name;
>
>
> class Disc
> array<Song*> songs;
>
>
> class Release
> array<Disc*> discs;
>
>
> class Artist
> array<Release*> releases;
>
>
> What I fdon't like about the above design is that there's not any OO'ness about
> it.

Dou you want a problem for your "OO"-solution or do you want a solution for
your problem? "Not being OO enough" is not an issue. Not being an appropriate
solution for a given problem surely is.

It is not "OO" if your problem demands associations (which, too, is "OO") and you
confound them with inheritance.

> array's could be lists, doesn't matter. If I have a pointer to a Song class,
> I don't have any oter information about the song. I can't get the Artist name,
> the release it came from, etc ... But what's good about it, as compared to the
> first example, is I only have 1 instance of the Artist class for each and every
> artist.

The second approach is better but still has shortcomings.
You should learn how to model associations between classes.
Good relational database design knowledge is very helpful.
Consider classes special cases of database tables. You may try to get a
normalized DB design. Then return back to C++ and adapt the design to
a class model.

Thereby you should learn how to model n:m associations in C++:

class Song
array<Disk*> disks;

// Simplistic:
Song::associate(Disk* dsk) {
disks.insert(dsk);
dsk->songs.insert(this);
}


Norbert


Lőrinczy Zsigmond

unread,
Mar 13, 2015, 7:59:20 AM3/13/15
to
On 2015-03-11 19:32, sdu...@gmail.com wrote:
>
>
> Hi, I am having a difficult time figuring out how I'm going to design my
> base and derived classes for a specific project.

Actually, it's not about classes and inheritance,
it's about data-organizations.
Maybe you could start here:

https://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model

Christian Gollwitzer

unread,
Mar 15, 2015, 8:49:48 AM3/15/15
to
Am 11.03.15 um 19:32 schrieb sdu...@gmail.com:
> Hi, I am having a difficult time figuringout how I'm going to design my
> base and derived classes for a specific project.
>
> What I'm looking to do is come up with a design for an efficient OO class design
> to represent songs in an Artists catalog. Songs at te lowest level. Then Discs
> becasue each song is contained on a disc within a particular release by the
> artist. And there are multiple releases. And multiple artists.

It seems to me that you are having only data, no code. Unless it is a
music simulator, where the artist can be triggered to play a song or the
like, the data would be best stored in a relational database. Retrieving
all songs from a given artist etc. would be almost trivial SQL queries.
OO doesn't fit it well IMHO - OO is about subjects, SQL about objects.

Christian

Richard Damon

unread,
Mar 15, 2015, 9:22:23 AM3/15/15
to
As others have said, Derivation isn't really the right tool for these
relationships.

A Disc isn't a special type of song, but is a collection of them
(actually, shouldn't it be a collection of releases?)

A Disc would should have a container of releases (this would need to be
a many-many container, as a given release might exist on several discs),
and those releases need a corresponding "other side" of the container to
have the list of discs they are on.

A Song would have a container of the releases that have been made of it,
and that release would need to have a back pointer to the song (I am
assuming that a release is only of a particular song).

Similarly Artist and Release will have some form of container to relate
them together (the type depends on if a release is allowed multiple
artists).

As was pointed out, a database will tend to naturally represent this
sort of interrelationships. If you really want to build this in memory
(or a piece of it in memory), you are really just building an in-memory
database representation, with inter-object relationships.

Glen Stark

unread,
Mar 15, 2015, 4:37:31 PM3/15/15
to
On Sun, 15 Mar 2015 09:22:02 -0400, Richard Damon wrote:

>> What I fdon't like about the above design is that there's not any
>> OO'ness about it.

Others are doing a fine job of helping you with your design question, I'd
just like talk a little about good C++ design.

Object-orientation is *tool*, not a *goal*. Important goals in software
design are correctness and clarity (always first and foremost),
simplicity, and suitability of purpose. In my lexicon, suitability of
purpose is how well does the code do its current and future job. If
code needs to be able to rapidly adapt to rapidly changing requirements,
flexibility is important. If it's in a performance-critical application
and performance has been measured to be a problem, efficiency becomes
important. Otherwise, what counts is does it do what it's supposed to?
If code isn't correct, it won't be suitable for it's purpose, regardless
of how efficient or flexible it is. If your code is sufficiently
efficient for its purpose, you should put it efficiency aside as
unimportant -- at least until you you have mastered writing code which is
good from these other, more important criteria. Same rule applies to
flexibility. With time you'll get a feel for what flexibility you need
to plan in in advance. Usually, you ain't gonna need it (YAGNI).

In my experience working with novice developers, if you focus on
correctness, simplicity and clarity, you typically wind up with more
flexible and efficient code than if you focus on efficiency and
flexibility in advance. Sad but true.

C++ supports generic, procedural, OO and functional programming. The
best C++ design makes good use of all three of these paradigms. My
impression is your goal is to improve your OO skills with this project,
which is laudable. So it's okay if you focus on OO for the sake of this,
or some other project. If however you see an area where using one of the
other paradigms seems simpler, that's what you should use. Here simpler
means simpler code, simpler design -- which usually means less code, less
multiplication of entities (classes, functions, lines of code). If you
make the decision to do something that isn't very OO, but produces
simpler, easier to read and maintain code, you have just practiced a
*very* useful skill: the wisdom of when *not* to use a language feature.

If on the other hand, using a class hierarchy seems to flow naturally
from the problem you are investigating you should do so. If in doubt,
sketch out an alternative (even a less OO one), and compare the
complexity of the two solutions. Which one more simply solves the
problems you will concretely have to face. Don't speculate too much
about possible, 'maybe we'll need' scenarios. That way lie dragons. A
good question to ask yourself before implementing a hierarchy is: will I
use these sub-classes as base-class? If the answer is no, inheritance is
probably the wrong way to accomplish what you are trying to accomplish.

Good luck

Glen

Paavo Helde

unread,
Mar 15, 2015, 5:20:04 PM3/15/15
to
Glen Stark <ma...@glenstark.net> wrote in
news:S3mNw.360450$L61.2...@fx30.am4:

> On Sun, 15 Mar 2015 09:22:02 -0400, Richard Damon wrote:
>
>>> What I fdon't like about the above design is that there's not any
>>> OO'ness about it.
>
> Others are doing a fine job of helping you with your design question,
> I'd just like talk a little about good C++ design.
>
> Object-orientation is *tool*, not a *goal*. Important goals in
> software design are correctness and clarity (always first and
> foremost), simplicity, and suitability of purpose.

Strictly speaking, clarity and simplicity are also tools, not goals. It's
just that in most cases there are no known alternatives which would work
better. In some cases, like in the obfuscated C contest, there are.

In the future, AI may take over most of the tasks of programmers, and it
might be that its operation will bear no resemblance to what humans would
consider simple or clear.

Cheers
Paavo

Jorgen Grahn

unread,
Mar 18, 2015, 5:43:36 PM3/18/15
to
On Sun, 2015-03-15, Glen Stark wrote:
...
> In my experience working with novice developers, if you focus on
> correctness, simplicity and clarity, you typically wind up with more
> flexible and efficient code than if you focus on efficiency and
> flexibility in advance. Sad but true.

Very true, but not sad. What's sad is how people are indoctrinated to
focus on efficiency and flexibility. I wonder why, since I've rarely
seen anyone gain anything by it. One or two guys selling books or
courses, but that's about it.

You get to spend more time writing and debugging lots of code, but I
suspect the increased risk of your company going bankrupt nullifies
that positive(?) effect.

[snip good advice]

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Message has been deleted

woodb...@gmail.com

unread,
Mar 18, 2015, 9:16:41 PM3/18/15
to
On Wednesday, March 18, 2015 at 5:37:22 PM UTC-5, Stefan Ram wrote:
> Jorgen Grahn <grahn...@snipabacken.se> writes:
> > What's sad is how people are indoctrinated to
> >focus on efficiency and flexibility.
>
> Learning C++ is only worth the effort if one cares for efficiency.
>
> For example, when one teaches rvalue references, what reason
> should one give why someone has to learn this if not efficiency?
>
> There are many other features in C++ only for the sake of efficiency.

And efficiency is a part of correctness. Performance related
bug reports should be welcomed.

Brian
Ebenezer Enterprises - Heavenly code.
http://webEbenezer.net

Jorgen Grahn

unread,
Mar 19, 2015, 2:46:56 PM3/19/15
to
On Wed, 2015-03-18, Stefan Ram wrote:
> Jorgen Grahn <grahn...@snipabacken.se> writes:
>> What's sad is how people are indoctrinated to
>> focus on efficiency and flexibility.

The flexibility part is what annoys me the most, but let's talk about
the efficiency part.

> Learning C++ is only worth the effort if one cares for efficiency.

Disagree. What other language would you use for large-ish projects?
I want static typing, a free, well-known language, and I don't want to
go back to C.

(Of course there are a lot of problems better solved in Perl, Python
or Bash.)

> For example, when one teaches rvalue references, what reason
> should one give why someone has to learn this if not efficiency?

It doesn't strike me as very important to teach it. What's important
is to teach people they can write maintainable but seemingly
inefficient code by relying on the standard library to use this
feature.

> There are many other features in C++ only for the sake of efficiency.

Agree. The language and the standard library has been designed to
(I think this is how Stroustrup phrased it) leave no room for a
lower-level language.

And yes, it's a problem. I myself am aware of the problem, but spend
a lot of time writing code which is more efficient than it actually
has to be. I'm indoctrinated, too.

On the other hand, when you need efficiency you need to have someone
around who's had experience with it. And it's been vital in most work
projects I've been in -- but not in /all/ of the code.

Christopher Pisz

unread,
Mar 19, 2015, 4:34:13 PM3/19/15
to
I've never had the pleasure of seeing anyone roll their own custom
classes that A) worked bug free and B) were more efficient than the STL,
while fulfilling the exact same requirements.

On the contrary, I've seen hundreds of custom implementations that were
both riddled with bugs and performed worse once looked at in a profiler.
Always, the author set out to make the mess in the name of efficiency.

I find it both egotistical and ignorant of some people to think they can
do better individually, then a committee of top C++ programmers and have
the confident that comes with the number of people using the STL for the
length of time it has been around.

None the less, I am not saying don't attempt it at all, but don't make a
practice of it, and if you do attempt it to fulfill some specific need,
profile it and test the hell out of it.

It makes my job very difficult to weed through 15 different "string"
classes and 20 different "my own speedy container" classes, riddles with
bugs in every project.

Additionally, it is very rare that efficiency was a higher priority
compared to maintainability. At least in my niche. I don't program hardware.


--
I have chosen to troll filter/ignore all subthreads containing the
words: "Rick C. Hodgins", "Flibble", and "Islam"
So, I won't be able to see or respond to any such messages
---

Öö Tiib

unread,
Mar 20, 2015, 11:26:13 AM3/20/15
to
C++ efficiency skill does not come from capability of copy-pasting thousands
of lines of bloat. Skill is to know what is out there, already written
and ready to use, and how good it is and for what. Just download boost.
It contains classes that are relatively bug free and are more efficient
than STL *in* *situations*. Fulfilling exact same requirements is pointless
because you need the operations that you use most often to be fast, and
do not care if the operations that you use rarely or never meet the
performance requirements.

I have seen orders of magnitude gains of efficiency of function from
simply replacing usage of containers. For example ´std::set´ with
´boost::flat_set´ or (not so simply) with ´boost::intrusive::set´.
In situations the difference can be like between 5 seconds and 8 minutes.
However you need someone who has experience with efficiency because
these things aren`t just more efficient as "silver bullets" but only
more efficient *in* *situations*.

> On the contrary, I've seen hundreds of custom implementations that were
> both riddled with bugs and performed worse once looked at in a profiler.
> Always, the author set out to make the mess in the name of efficiency.
>
> I find it both egotistical and ignorant of some people to think they can
> do better individually, then a committee of top C++ programmers and have
> the confident that comes with the number of people using the STL for the
> length of time it has been around.

Very true. I have even seen memory leak in STL that Microsoft SOLD to me.
It fixed it with service pack few months later. With gcc it is fairly
*common* to have some subtle defects. Verdict: Even the "top programmers"
just can´t write things without defects.

Therefore what average Joe writes is typically naive to no repair.
Someone familiar with efficiency isn´t exactly average Joe. Only about
10% of C++ developers can use profiler and do understand what they see
with it. Less than 5% can read source code of STL or boost fluently.
So the problem of Joe is that his best option is to use the header-only
code that he can´t neither read nor measure. He is afraid and so he
writes his silly classes. FUD, but he can´t say it is his FUD and so he
will say "efficiency", because only 10% are capable of measuring it.
So solution to your problems is like Jorgen said, to have someone around
who has experience with efficiency ... and that in style of C++.

Jorgen Grahn

unread,
Mar 21, 2015, 11:33:39 AM3/21/15
to
For the record, I was unclear when I wrote "when you need efficiency
you need to have someone around who's had experience with it" above.
I meant we could write most C++ code as if it was Python or something.
Not avoid heap allocation, not avoid copying objects etc -- ignoring
all the performance-oriented tricks we have been taught. We would
still meet the performance requirements ... but then we would be badly
prepared in the relatively small areas where we /do/ need performance.

I'm not necessarily disagreeing with what you write, except I hope
more than 10% know how to use a profiler (if they don't we should
teach them).

Öö Tiib

unread,
Mar 22, 2015, 12:48:08 PM3/22/15
to
Indeed it is typically wast majority of code-base that may be written
without considering performance. Also it takes expert to just guess
what the "tiny minority" likely is before application is written.
It is because the goals and focus of applications tend to shift and
change during writing. So it is always worth to require clarity,
robustness and maintainability even in modules whose performance is
irrelevant because software tends to change and evolve rapidly before
it becomes mature.

Performance and robustness are orthogonal but not totally orthogonal
things. I have found that hard to follow algorithm or I/O communication
logic or data layout often tends to have (or after some defect fixing
lead to) performance issues as well.

> We would
> still meet the performance requirements ... but then we would be badly
> prepared in the relatively small areas where we /do/ need performance.

Yes, that was what I was writing ... people who quickly see what should
be done to make an annoyingly slow thing 20 times faster are rare.

> I'm not necessarily disagreeing with what you write, except I hope
> more than 10% know how to use a profiler (if they don't we should
> teach them).

If work is going in decent-sized teams then most actually even don't
need to learn to handle profiler at all unless they are really
interested about it. Anecdotal example: a young coworker suggested
that why don't we write a framework that logs and counts what calls
what and how many times run time. Others said that because profiler
does it already finely among lot of other useful things. :)

What bothers me more is that lot of C++ programmers can't use debugger
unless it is integrated to IDE (by someone else). It is usually done
for desktop applications but more than half of work is about embedded
stuff. Need an IDE then integrate embedded debugger to it yourself. :(

woodb...@gmail.com

unread,
Mar 22, 2015, 10:05:04 PM3/22/15
to
I haven't heard this "Optimized C++" book mentioned on the
newsgroup yet:

http://www.amazon.com/Optimized-C-Kurt-Guntheroth/dp/1491922060/ref=sr_1_12?s=books&ie=UTF8&qid=1427075517&sr=1-12&keywords=c%2B%2B



> > I'm not necessarily disagreeing with what you write, except I hope
> > more than 10% know how to use a profiler (if they don't we should
> > teach them).
>
> If work is going in decent-sized teams then most actually even don't
> need to learn to handle profiler at all unless they are really
> interested about it. Anecdotal example: a young coworker suggested
> that why don't we write a framework that logs and counts what calls
> what and how many times run time. Others said that because profiler
> does it already finely among lot of other useful things. :)
>

Does anyone use hwpcm on FreeBSD. I was trying to use it
recently but couldn't figure it out.

pcmstat ls

gave me a help page and

pcmstat -S instructions -T

said something about a library not loading. I may need to
install something.


Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net

seeplus

unread,
Mar 22, 2015, 11:40:27 PM3/22/15
to
On Monday, March 23, 2015 at 1:05:04 PM UTC+11, woodb...@gmail.com wrote:
>
> I haven't heard this "Optimized C++" book mentioned on the
> newsgroup yet:
>
> http://www.amazon.com/Optimized-C-Kurt-Guntheroth/dp/1491922060/ref=sr_1_12?s=books&ie=UTF8&qid=1427075517&sr=1-12&keywords=c%2B%2B
>

Last I looked he had written the first 3 chapters out of a scheduled
11 chapters, and it has a proposed August release.

A bit early to be able comment on it and the Ebook has too high a $ tag to just
purchase on spec.
But sounds like it has good ideas.

0 new messages