[Tutor] class question

Steven D'Aprano steve at pearwood.info
Wed Jan 26 02:46:38 CET 2011


Elwin Estle wrote:

> Is it better to have one large sort of "do it all" class, or break
> the larger class up into smaller classes?

Yes.

Or no.

It's impossible to answer that question definitively without knowing 
more about what "it all" is. But I can give some general advice:

* Python isn't Java. Don't feel that you must use classes. If your 
problem is better solved using a procedural or functional approach, go 
right ahead and use it. Classes aren't compulsory.

* The standard model which you should use it:

   verbs -> functions or methods
   nouns -> classes or attributes

   You should be able to answer the question "What *thing* does
   your class represent?". (The answer can be an abstract thing,
   but it should be a thing.)

   If you can't answer that question, then you shouldn't use a
   class. You should solve the problem using stand-alone functions.

* Think about "is-a" and "has-a" relationships:

   - if x is a Foo, then use a class Foo and make x an instance of Foo
   - if x has a Foo, then give x an attribute x.foo which is a Foo


* Classes should represent a *single* well-defined thing. That might be 
a compound thing, or a collection of things -- the class represents the 
entire collection. If the thing is made of parts, each part could be 
represented by an attribute. This is okay:

class Coffee:
     def __init__(self):
         self.style = 'white'
         self.milk = 'full cream'
         self.sugars = 1
         self.size = 'regular'

class Pie:
     def __init__(self):
         self.kind = 'cherry'
         self.slices = 1
         self.with_cream = False

class SpecialOfTheDay:
     def __init__(self):
         self.drink = Coffee()
         self.snack = Pie()

But don't design a class like this:

class CoffeeAndPie:
     def __init__(self):
         self.style = 'white'
         self.milk = 'full cream'
         self.sugars = 1
         self.size = 'regular'
         self.kind = 'cherry'
         self.slices = 1
         self.with_cream = False

One slice of coffee? Oh really?


* Classes should be more general rather than too specific. But don't go 
crazy and make it so abstract that you run out of air to breathe, and 
nobody can understand what the hell the class is for:

http://www.joelonsoftware.com/articles/fog0000000018.html

* Coupling is usually bad. Aim to reduce coupling, unless you have a 
good reason for wanting strongly coupled systems. What's coupling? A key 
and a lock are *highly* coupled: only one key will fit the lock, and no 
other key will do the job. But, say, a knife and a steak are loosely 
coupled. Any sharp knife will cut a steak. Sure, some knives are better 
than others, but at a pitch, you could even use a blunt butter-knife and 
a lot of effort. Another example: your clothes iron and ironing board 
have very loose coupling. You can use any iron on any board, and it will 
be just fine. But the memory cards in your computer are moderately 
coupled with the motherboard: only some memory cards will fit. You can't 
use a 1980 64K memory card in a 2011 motherboard. But provided the 
memory will fit, it doesn't matter which card you use.

* One way to reduce coupling is with the Law of Demeter: if you want 
your dog to walk, don't talk to your dog's legs. You will only confuse 
the dog and it won't get anywhere.

http://en.wikipedia.org/wiki/Law_of_Demeter



Hope this helps.



-- 
Steven



More information about the Tutor mailing list