Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder1.news.weretis.net!news1.tnib.de!feed.news.tnib.de!news.tnib.de!newsfeed.freenet.ag!news2.euro.net!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.033 X-Spam-Evidence: '*H*': 0.93; '*S*': 0.00; 'represents': 0.05; 'dev': 0.07; 'explicit': 0.07; 'lines,': 0.07; 'correct,': 0.09; 'global,': 0.09; 'span': 0.09; 'api': 0.11; 'stored': 0.12; 'creates': 0.14; 'globals': 0.16; 'implies': 0.16; 'inheritance': 0.16; 'reasonable.': 0.16; 'subject:sub': 0.16; 'tables,': 0.16; '\xa0what': 0.16; 'wrote:': 0.18; 'later': 0.20; 'example': 0.22; 'instance,': 0.24; 'login': 0.25; 'sort': 0.25; '>': 0.26; 'class.': 0.26; 'pass': 0.26; 'asking': 0.27; 'header:In-Reply- To:1': 0.27; 'rest': 0.29; 'am,': 0.29; 'database,': 0.30; 'have,': 0.30; 'message-id:@mail.gmail.com': 0.30; 'along': 0.30; "i'm": 0.30; 'code': 0.31; "d'aprano": 0.31; 'object.': 0.31; 'stands': 0.31; 'steven': 0.31; 'work:': 0.31; 'class': 0.32; 'figure': 0.32; 'guess': 0.33; 'not.': 0.33; 'device': 0.34; 'maybe': 0.34; 'could': 0.34; 'basic': 0.35; 'agree': 0.35; 'anywhere': 0.35; 'classes': 0.35; 'connection': 0.35; 'good.': 0.35; 'one,': 0.35; 'test': 0.35; 'but': 0.35; 'received:google.com': 0.35; '+0200,': 0.36; 'accessing': 0.36; 'object,': 0.36; 'oracle': 0.36; 'useful': 0.36; 'subject:?': 0.36; 'should': 0.36; 'throughout': 0.37; 'easily': 0.37; 'skip:& 10': 0.38; 'handle': 0.38; 'whatever': 0.38; 'to:addr:python- list': 0.38; 'expect': 0.39; 'skip:& 20': 0.39; 'does': 0.39; 'use.': 0.39; 'sure': 0.39; 'to:addr:python.org': 0.39; 'how': 0.40; 'even': 0.60; 'is.': 0.60; 'skip:n 30': 0.60; 'most': 0.60; 'course': 0.61; 'making': 0.63; 'skip:n 10': 0.64; 'different': 0.65; 'needing': 0.65; 'production': 0.68; 'yes': 0.68; 'sound': 0.68; 'connection.': 0.74; 'skip:n 40': 0.81; 'us?': 0.84; 'device,': 0.91; 'device.': 0.93; 'imagine': 0.93; 'connection,': 0.95; '2013': 0.98 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:x-received:in-reply-to:references:date:message-id :subject:from:to:content-type; bh=w6bo2xbhrqdy+nagO9iRdKkDnxjyXqZfhbTccnEcDA0=; b=tC8GyG8MWDuLmnYGu9yuc977I86B85nWEWuqUPv+clo8YEn0X7aUHR+aZtxYI8mM/W iID8+m2aaLXov0E3fsHbUExzLz0G+3oKx0ScecGc46fH4mZq+jG+UJHTTj2qE22Ck3kB aqa1+SdMQ5uSaOShJ7l7BI2z4NMi60wupLOn+m/PLWljTuQwqfHgCplbssnkyZQ649NM ItvfG7fjQfeNfPajuzU7f6HToaI1Wz7c6jgxJUbzd3AyDFWZfVLNtpwu7dJ4/96ljvO7 SlgvUAgQBYkmxlsAuDQTKMhqbnqVvqjZUk8jTnjNL8F5pYl+7dWACYHNHiUDad5isPLP xshg== MIME-Version: 1.0 X-Received: by 10.112.74.98 with SMTP id s2mr11202889lbv.9.1365493102205; Tue, 09 Apr 2013 00:38:22 -0700 (PDT) In-Reply-To: <5163be52$0$29977$c3e8da3$5496439d@news.astraweb.com> References: <5163be52$0$29977$c3e8da3$5496439d@news.astraweb.com> Date: Tue, 9 Apr 2013 09:38:21 +0200 Subject: Re: classes and sub classes? From: Morten Guldager To: python-list@python.org Content-Type: multipart/alternative; boundary=14dae94738cd4ce3ed04d9e8a3f9 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 172 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1365493105 news.xs4all.nl 6964 [2001:888:2000:d::a6]:58736 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:43131 --14dae94738cd4ce3ed04d9e8a3f9 Content-Type: text/plain; charset=ISO-8859-1 On Tue, Apr 9, 2013 at 9:08 AM, Steven D'Aprano < steve+comp.lang.python@pearwood.info> wrote: > On Tue, 09 Apr 2013 07:50:11 +0200, Morten Guldager wrote: > > > I'm about to write an API against a huge propitiatory Oracle based > > network inventory database. The database have many different concepts > > stored in it's tables, can one concept can span over multiple tables. > > > > I would like to write a class for accessing each concept, but only have > > a single database connection throughout the whole program. > > Sounds reasonable. > > > I imagine some code along these lines, but cant figure out how to > > declare the classes that will make it work: > > > > # create a connection to the database and perform come basic login and > > initialization > > nib = NwInvDb("scott/tiger@ora") > > # find a device by ip > > interesting_device = nib.Device.lookup_by_ip("192.168.1.1") > > What's "nib" mean? And "NwInvDb"? I can imagine that the "Db" at the end > stands for Database, but the rest is just word-salad. I can guess that > NwInvDb is some sort of database connection. Am I close? > NwInvDb = NetworkInventoryDatabase, yes you are correct, it creates the database handle and makes it ready for use. > In this example I access the concept Device. > > > > Should I make the Device class inherit from NwInvDb? Or should I keep > > them separate? > > Why are you asking us? We don't know what functionality you expect NwInvDb > and Device to have, what they represent, or whether a Device can be > meaningfully considered an instance of a NwInvDb, whatever that is. > > But given my *guess* that NwInvDb represents a database connection, and > that Device represents data fetched from that database, then no of course > you should not inherit. Inheritance implies an "is-a" relationship. If > you inherit from NwInvDb for Device, that implies: > > - interesting_device Is-A database; > which it is not. - anywhere you can use a NwInvDb database object, you can use > a Device object. > which you can not. And the same would apply to every other concept in the database. > > That does not sound like a clean and useful design to me. > Good. I think I agree with you so far. Maybe that's why I'm asking, because I'm not perfectly sure which path to follow to achieve what I want. Yes, I need some sort of database connection instance, if it wasn't because I later on will be needing to access both test and production database I _could_ have made it global, even if we easily could agree that globals suck most of the time! The concept classes like the Device one, will be using the database instance, I just don't know how to pass db into the concept class. - should I do it explicit making constructors accept an argument? Like: nib = NwInvDb("scott/tiger@ora") dev = NwInvDb.Device(nib) interesting_device = dev.lookup_by_ip("192.168.1.1") -- /Morten %-) --14dae94738cd4ce3ed04d9e8a3f9 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable On Tue, Apr 9, 2013 at 9:08 AM, Steven D'Aprano <<= a href=3D"mailto:steve+comp.lang.python@pearwood.info" target=3D"_blank">st= eve+comp.lang.python@pearwood.info> wrote:
On Tue, 09 Apr 2013 07:50:= 11 +0200, Morten Guldager wrote:

> I'm about to write an API against a huge propitiatory Oracle b= ased
> network inventory database. The database have many different concepts<= br> > stored in it's tables, can one concept can span over multiple tabl= es.
>
> I would like to write a class for accessing each concept, but only hav= e
> a single database connection throughout the whole program.

Sounds reasonable.

> I imagine some code along these lines, but cant figure out how to
> declare the classes that will make it work:
>
> # create a connection to the database and perform come basic login and=
> initialization
> nib =3D NwInvDb("scott/tiger@ora")
> # find a device by ip
> interesting_device =3D nib.Device.lookup_by_ip("192.168.1.1"= )

What's "nib" mean? And "NwInvDb"? I can imagi= ne that the "Db" at the end
stands for Database, but the rest is just word-salad. I can guess that
NwInvDb is some sort of database connection. Am I close?

NwInvDb =3D NetworkInventoryDatabase, yes you are correct= , it creates the database handle and makes it ready for use.=A0

> In this example I access the concept Device.
>
> Should I make the Device class inherit from NwInvDb? Or should I keep<= br> > them separate?

Why are you asking us? We don't know what functionality you expec= t NwInvDb
and Device to have, what they represent, or whether a Device can be
meaningfully considered an instance of a NwInvDb, whatever that is.

But given my *guess* that NwInvDb represents a database connection, and
that Device represents data fetched from that database, then no of course you should not inherit. Inheritance implies an "is-a" relationshi= p. If
you inherit from NwInvDb for Device, that implies:

- interesting_device Is-A database;

whi= ch it is not.=A0

- anywhere you can use a NwInvDb database object, you can use
=A0 a Device object.

which you can not.= =A0

And the same would apply to every other concept in the database.

That does not sound like a clean and useful design to me.
<= div>
Good. I think I agree with you so far. Maybe that's = why I'm asking, because I'm not perfectly sure which path to follow= to achieve =A0what I want.

Yes, I need some sort of database connection instance, = if it wasn't because I later on will be needing to access both test and= production database I _could_ have made it global, even if we easily could= agree that globals suck most of the time!

The concept classes like the Device one, will be using = the database instance, I just don't know how to pass db into the concep= t class. - should I do it explicit making constructors accept an argument? = Like:

nib =3D NwInvDb("scott/tiger@ora")
= dev =3D NwInvDb.Device(nib)
interesting_device =3D dev.lookup_by_= ip("192.168.1.1")


-- /Morten %-)=20 --14dae94738cd4ce3ed04d9e8a3f9--