[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-devel
Subject: Re: OO design help
From: "Nathan Bradshaw" <nathanlbradshaw () gmail ! com>
Date: 2008-07-21 18:53:35
Message-ID: 92af7fc70807211153x2c6f5f46t94a02348295866b () mail ! gmail ! com
[Download RAW message or body]
[Attachment #2 (multipart/alternative)]
On Mon, Jul 21, 2008 at 7:37 AM, Sebastian Tr=FCg <trueg@k3b.org> wrote:
> On Saturday 19 July 2008 00:50:32 Nathan Bradshaw wrote:
> > On Fri, Jul 18, 2008 at 3:44 AM, Sebastian Tr=FCg <trueg@k3b.org> wrote=
:
> > > On Thursday 17 July 2008 19:57:10 Nathan Bradshaw wrote:
> > > > On Thu, Jul 17, 2008 at 4:31 AM, Sebastian Tr=FCg <trueg@k3b.org>
> wrote:
> > > > > On Tuesday 15 July 2008 13:35:27 Nathan Bradshaw wrote:
> > > > > > Hi all, one of the last things I want to do to finish up the KD=
E
> > > > > > musicbrainz lib I've been building is to replace my local
> > > > > > album/release/track classes with a set of interface classes tha=
t
> > >
> > > actual
> > >
> > > > > > real software (rather than my toy test progs) can implement
> > > > > > alongside whatever their native representation of music metadat=
a
> > > > > > is. My libs
> > >
> > > can
> > >
> > > > > then
> > > > >
> > > > > > just operate on this interface and I won't be duplicating (in a
> > > > > > probably less functional way) the metadata structures in other
> > > > > > applications.
> > > > >
> > > > > Just to clarify: are your libs using the interface or providing i=
t?
> > > >
> > > > Providing it. My thinking on this is that rather than try and force
> > >
> > > people
> > >
> > > > to implement a musicbrainz specific set of classes that will probab=
ly
> > >
> > > serve
> > >
> > > > as nothing more than transfer points between the m/brainz service a=
nd
> > > > the client app's own, more specialized, meta data class model my li=
b
> > > > will
> > >
> > > just
> > >
> > > > provide a set of abstract interface classes that client apps can th=
en
> > > > implement in what ever way makes most sense for them.
> > > >
> > > > The musicbrainz lib would then just have a bunch of functions that =
it
> > > > performs against classes that implement the interface. The main
> > >
> > > operations
> > >
> > > > would be creation and visiting combined with update / creation (for
> > >
> > > example
> > >
> > > > when an existing local hierarchy is refreshed from the musicbrainz
> > >
> > > service,
> > >
> > > > say when an artist releases a new album)
> > >
> > > I don't really get this. If your libs are providing the interface why
> > > would clients implement it? The way I understand it the client would
> use
> > > the interface the lib provides, ie. it calls methods from your
> interface.
> >
> > I think we might be having terminology issues :)
> >
> > API wise, the lib provides what you'd expect: look up artist by name, g=
et
> > album by CD ID that sort of thing. What I've be going on about though i=
s
> > the set of abstract base classes I'm knocking together that client code
> > could inherit from to interact with the library.
> >
> > My thinking is, most client code is going to have an existing hierarchy
> of
> > some form already to represent the typical
> >
> MusicCollection->Artist->ReleaseCollection->Release->TrackCollection->Tra=
ck
> > hierarchy and it could be implemented with any number of possible back
> > ends. For a situation like a CDDB or musicbrainz lookup of a CD etc the=
re
> > is not a lot of overhead in creating the quite small object hierarchy t=
o
> > represent a single release, but I think its a different story for an
> > application like say a music manager application. Lets say this Mythica=
l
> > Music Manager provides a batch operation like trying to best guess
> identify
> > all your badly labeled, possibly duplicated music files and which artis=
t
> /
> > album they belong to. If you've already parsed the collection into a
> > hierarchy, and lets say its a big collection, and then you've walked th=
at
> > hierarchy and sent off a big bunch of queries to musicbrainz you would
> then
> > end up with a second big hierarchy returned to you. Instead, if the MMM
> > collection hierarchy through either interface classes or multiple
> > inheritance supported it's own as well as the musicbrainz lib class
> models
> > then the MMM collection would be passed to and updated by the musicbrai=
nz
> > lib query functions.
>
> So you want clients to use your lib implicately by inheriting from its
> classes
> to allow internal updating. Example:
Yup, thats correct.
>
>
> class ClientTrack : public YourLib::Track
> {
> void update() {
> YourLib::Track::getStuffFromMusicBrainz();
> doSomethingWithTheNewInformationNowAlreadyStoredInTheObject();
> }
> };
>
> Right?
>
> > > Or do you mean that the one interface should be provided by several
> > > music-information libs or services, providing data from different
> sources
> > > through one API?
> > >
> > > > > [If its the latter: Did you have a look at libkcddb (which has no
> > > > > maintainer
> > > > > AFAIK). Maybe you could build upon that?]
> > > >
> > > > Nope, haven't looked at the cddb lib, will do when I get home from
> work
> > > > tonight.
> > > >
> > > > > > One thing that is getting me is when I try to come up with a wa=
y
> to
> > > > > > represent container classes for things like an artist's release
> > > > >
> > > > > collection.
> > > > >
> > > > > > In an effort to not force implementation decisions on clients, =
it
> > >
> > > would
> > >
> > > > > > seem that the way to go would be to specify a collection class
> that
> > > > > > provided accessors, iterators etc and allow the client to speci=
fy
> > > > > > the implementation (QList or what have you).
> > > > > >
> > > > > > My other concern is how to represent the relationship between a
> > >
> > > higher
> > >
> > > > > > order class such as an artist and their release collection. Is =
it
> > > > > > enough
> > > > >
> > > > > to
> > > > >
> > > > > > just specify in the artist interface that it return a reference
> to
> > > > > > an object implementing the releasecollection interface? This
> scares
> > > > > > me a bit as it means implementations will probably end up passi=
ng
> > > > > > out handles to member data structures. Is this a valid concern
> for
> > > > > > an interface designer or is that a problem that gets passed on =
to
> > > > > > the client code?
> > > > >
> > > > > I think the proper encapsulation cannot be enforced completely be
> the
> > > > > interface designer. One could still code a class that would expos=
e
> > > > > members. QT4 tends to return shared copies of almost everything.
> This
> > > > > makes usage very
> > > > > easy and you don't have to care about exposing internal data
> members
> > > > > since changes will return in a deep copy.
> > > > >
> > > > > More after clarifying the question above. ;)
> > > >
> > > > I guess the area that I'm going back and forth on the most is how t=
o
> > >
> > > model
> > >
> > > > the container classes in a way that doesn't force implementation
> > >
> > > decisions
> > >
> > > > on the client. If I define an interface that is essentially a subse=
t
> of
> > > > a typical QList type container class with the basic accessors and
> > > > modifiers required for the lib to do it's job then clients can put
> > > > regular containers, databases or any other type of back end behind
> it,
> > > > which is what I'm looking for.
> > > >
> > > > WRT encapsulation, my concern is that an interface class such as
> > > > IArtist would have to offer non-const access to an object that
> > > > implements the IReleaseList container, which in turn leads to
> exposing
> > > > the IArtist implementation's internals. Is this a valid concern?
> > >
> > > not really. It is pretty simple to solve this problem. Either with
> shared
> > > copies or with a combination or const and non-const access methods.
> > > Imagine this:
> > >
> > > class IArtist {
> > > const IRelease* release( int i ) const:
> > > IRelease* release( int i );
> > > }
> > >
> > > or
> > > class IArtist {
> > > IRelease release( int i ) const;
> > > IRelease& release( int i );
> > > }
> > >
> > > Both allow to change a non-const Artist object while disallowing acce=
ss
> > > to a
> > > const one. The second one is more along the lines of the QT4 way.
> > >
> > > Cheers,
> > > Sebastian
> >
> > Thanks Sebastian, I think that I was just over-thinking this issue!
> >
> > > >> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to
> > >
> > > unsubscribe <<
>
>
>
> >> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to
> unsubscribe <<
>
[Attachment #5 (text/html)]
<div dir="ltr"><br><br><div class="gmail_quote">On Mon, Jul 21, 2008 at 7:37 AM, \
Sebastian Trüg <<a href="mailto:trueg@k3b.org">trueg@k3b.org</a>> \
wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, \
204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> <div><div></div><div \
class="Wj3C7c">On Saturday 19 July 2008 00:50:32 Nathan Bradshaw wrote:<br> > On \
Fri, Jul 18, 2008 at 3:44 AM, Sebastian Trüg <<a \
href="mailto:trueg@k3b.org">trueg@k3b.org</a>> wrote:<br> > > On Thursday 17 \
July 2008 19:57:10 Nathan Bradshaw wrote:<br> > > > On Thu, Jul 17, 2008 at \
4:31 AM, Sebastian Trüg <<a href="mailto:trueg@k3b.org">trueg@k3b.org</a>> \
wrote:<br> > > > > On Tuesday 15 July 2008 13:35:27 Nathan Bradshaw \
wrote:<br> > > > > > Hi all, one of the last things I want to do to \
finish up the KDE<br> > > > > > musicbrainz lib I've been building \
is to replace my local<br> > > > > > album/release/track classes with \
a set of interface classes that<br> > ><br>
> > actual<br>
> ><br>
> > > > > real software (rather than my toy test progs) can \
implement<br> > > > > > alongside whatever their native representation \
of music metadata<br> > > > > > is. My libs<br>
> ><br>
> > can<br>
> ><br>
> > > > then<br>
> > > ><br>
> > > > > just operate on this interface and I won't be \
duplicating (in a<br> > > > > > probably less functional way) the \
metadata structures in other<br> > > > > > applications.<br>
> > > ><br>
> > > > Just to clarify: are your libs using the interface or providing \
it?<br> > > ><br>
> > > Providing it. My thinking on this is that rather than try and \
force<br> > ><br>
> > people<br>
> ><br>
> > > to implement a musicbrainz specific set of classes that will \
probably<br> > ><br>
> > serve<br>
> ><br>
> > > as nothing more than transfer points between the m/brainz service \
and<br> > > > the client app's own, more specialized, meta data class \
model my lib<br> > > > will<br>
> ><br>
> > just<br>
> ><br>
> > > provide a set of abstract interface classes that client apps can \
then<br> > > > implement in what ever way makes most sense for them.<br>
> > ><br>
> > > The musicbrainz lib would then just have a bunch of functions that \
it<br> > > > performs against classes that implement the interface. The \
main<br> > ><br>
> > operations<br>
> ><br>
> > > would be creation and visiting combined with update / creation \
(for<br> > ><br>
> > example<br>
> ><br>
> > > when an existing local hierarchy is refreshed from the musicbrainz<br>
> ><br>
> > service,<br>
> ><br>
> > > say when an artist releases a new album)<br>
> ><br>
> > I don't really get this. If your libs are providing the interface \
why<br> > > would clients implement it? The way I understand it the client \
would use<br> > > the interface the lib provides, ie. it calls methods from \
your interface.<br> ><br>
> I think we might be having terminology issues :)<br>
><br>
> API wise, the lib provides what you'd expect: look up artist by name, \
get<br> > album by CD ID that sort of thing. What I've be going on about \
though is<br> > the set of abstract base classes I'm knocking together that \
client code<br> > could inherit from to interact with the library.<br>
><br>
> My thinking is, most client code is going to have an existing hierarchy of<br>
> some form already to represent the typical<br>
> MusicCollection->Artist->ReleaseCollection->Release->TrackCollection->Track<br>
> hierarchy and it could be implemented with any number of possible back<br>
> ends. For a situation like a CDDB or musicbrainz lookup of a CD etc there<br>
> is not a lot of overhead in creating the quite small object hierarchy to<br>
> represent a single release, but I think its a different story for an<br>
> application like say a music manager application. Lets say this Mythical<br>
> Music Manager provides a batch operation like trying to best guess identify<br>
> all your badly labeled, possibly duplicated music files and which artist /<br>
> album they belong to. If you've already parsed the collection into a<br>
> hierarchy, and lets say its a big collection, and then you've walked \
that<br> > hierarchy and sent off a big bunch of queries to musicbrainz you would \
then<br> > end up with a second big hierarchy returned to you. Instead, if the \
MMM<br> > collection hierarchy through either interface classes or multiple<br>
> inheritance supported it's own as well as the musicbrainz lib class \
models<br> > then the MMM collection would be passed to and updated by the \
musicbrainz<br> > lib query functions.<br>
<br>
</div></div>So you want clients to use your lib implicately by inheriting from its \
classes<br> to allow internal updating. Example:</blockquote><div><br>Yup, thats \
correct. <br> </div><blockquote class="gmail_quote" style="border-left: 1px \
solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br>
<br>
class ClientTrack : public YourLib::Track<br>
{<br>
void update() {<br>
YourLib::Track::getStuffFromMusicBrainz();<br>
doSomethingWithTheNewInformationNowAlreadyStoredInTheObject();<br>
}<br>
};<br>
<br>
Right?<br>
<div><div></div><div class="Wj3C7c"><br>
> > Or do you mean that the one interface should be provided by several<br>
> > music-information libs or services, providing data from different \
sources<br> > > through one API?<br>
> ><br>
> > > > [If its the latter: Did you have a look at libkcddb (which has \
no<br> > > > > maintainer<br>
> > > > AFAIK). Maybe you could build upon that?]<br>
> > ><br>
> > > Nope, haven't looked at the cddb lib, will do when I get home from \
work<br> > > > tonight.<br>
> > ><br>
> > > > > One thing that is getting me is when I try to come up with a \
way to<br> > > > > > represent container classes for things like an \
artist's release<br> > > > ><br>
> > > > collection.<br>
> > > ><br>
> > > > > In an effort to not force implementation decisions on \
clients, it<br> > ><br>
> > would<br>
> ><br>
> > > > > seem that the way to go would be to specify a collection \
class that<br> > > > > > provided accessors, iterators etc and allow \
the client to specify<br> > > > > > the implementation (QList or what \
have you).<br> > > > > ><br>
> > > > > My other concern is how to represent the relationship \
between a<br> > ><br>
> > higher<br>
> ><br>
> > > > > order class such as an artist and their release collection. \
Is it<br> > > > > > enough<br>
> > > ><br>
> > > > to<br>
> > > ><br>
> > > > > just specify in the artist interface that it return a \
reference to<br> > > > > > an object implementing the \
releasecollection interface? This scares<br> > > > > > me a bit as it \
means implementations will probably end up passing<br> > > > > > out \
handles to member data structures. Is this a valid concern for<br> > > > \
> > an interface designer or is that a problem that gets passed on to<br> > \
> > > > the client code?<br> > > > ><br>
> > > > I think the proper encapsulation cannot be enforced completely be \
the<br> > > > > interface designer. One could still code a class that \
would expose<br> > > > > members. QT4 tends to return shared copies of \
almost everything. This<br> > > > > makes usage very<br>
> > > > easy and you don't have to care about exposing internal data \
members<br> > > > > since changes will return in a deep copy.<br>
> > > ><br>
> > > > More after clarifying the question above. ;)<br>
> > ><br>
> > > I guess the area that I'm going back and forth on the most is how \
to<br> > ><br>
> > model<br>
> ><br>
> > > the container classes in a way that doesn't force \
implementation<br> > ><br>
> > decisions<br>
> ><br>
> > > on the client. If I define an interface that is essentially a subset \
of<br> > > > a typical QList type container class with the basic accessors \
and<br> > > > modifiers required for the lib to do it's job then clients \
can put<br> > > > regular containers, databases or any other type of back \
end behind it,<br> > > > which is what I'm looking for.<br>
> > ><br>
> > > WRT encapsulation, my concern is that an interface class such as<br>
> > > IArtist would have to offer non-const access to an object that<br>
> > > implements the IReleaseList container, which in turn leads to \
exposing<br> > > > the IArtist implementation's internals. Is this a \
valid concern?<br> > ><br>
> > not really. It is pretty simple to solve this problem. Either with \
shared<br> > > copies or with a combination or const and non-const access \
methods.<br> > > Imagine this:<br>
> ><br>
> > class IArtist {<br>
> > const IRelease* release( int i ) const:<br>
> > IRelease* release( int i );<br>
> > }<br>
> ><br>
> > or<br>
> > class IArtist {<br>
> > IRelease release( int i ) const;<br>
> > IRelease& release( int i );<br>
> > }<br>
> ><br>
> > Both allow to change a non-const Artist object while disallowing access<br>
> > to a<br>
> > const one. The second one is more along the lines of the QT4 way.<br>
> ><br>
> > Cheers,<br>
> > Sebastian<br>
><br>
> Thanks Sebastian, I think that I was just over-thinking this issue!<br>
><br>
> > >> Visit <a \
href="http://mail.kde.org/mailman/listinfo/kde-devel#unsub" \
target="_blank">http://mail.kde.org/mailman/listinfo/kde-devel#unsub</a> to<br> > \
><br> > > unsubscribe <<<br>
<br>
<br>
<br>
>> Visit <a href="http://mail.kde.org/mailman/listinfo/kde-devel#unsub" \
target="_blank">http://mail.kde.org/mailman/listinfo/kde-devel#unsub</a> to \
unsubscribe <<<br> </div></div></blockquote></div><br></div>
>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic