[Tutor] two questions..

Israel Evans israel@lith.com
Thu, 15 Nov 2001 08:13:34 -0800


   Thank you so much!  You explain this very well!  Now I know I will
definitely have to get that book.

Thanks!

-----Original Message-----
From: dman [mailto:dsh8290@rit.edu]
Sent: Wednesday, November 14, 2001 8:05 PM
To: [tutor]
Subject: Re: [Tutor] two questions..


On Wed, Nov 14, 2001 at 03:56:34PM -0800, Israel Evans wrote:
| 
| ||  Some of this is a bit confusing to me :
| 
| Hmmm, let me try the body analogy, since that seems to be where my head
is.
| :)
| 
| Let's say that you have a formula for specifying what percentage of body
fat
| that a particular region of the body should have.  All constraints of
| minimum and maximum aside, if we wanted to change the weight of the body
but
| have the specified body part deviate from it's normal fat distribution,
how
| would this best be set up?   Ok now for D&D analogies...  If you got two
| magical rings of Polymorphism, one that made you hugely fat and one that
| reduced that annoying wiggly neck wattle, we would need to have some sort
of
| object that affected the normal way in which calculations are done on our
| character.
| 
| Could this be done by having the regular calculations for body weight look
| for any modifier thingamabobs and if it found some, factor that into the
| calculations, and if not, then just do the calculations as normal?

This can be done, however you are more likely to end up with spaghetti
code (error-prone too) as you increase the number of magic flags the
computation depends on.

For something like this I would recommend the Strategy pattern.
Basically you would define a function that performs the computation
for only a single situation (no magic flags).  You can define any
number of these functions.  Then you give this function to your object
and this function determines how the object behaves.

An example :

def default_strat( weight ) :
    """
    This function is the default strategy we will give our body part.
    Given the weight of the body part, it returns the weight of the
    fat in the body part.
    """
    return (weight * 0.20)
    

class BodyPart :
    def __init__( self , weight ) :
        self.weight = weight # the weight of the body part

    def change_strategy( self , new_strat ) :
        """
        Provide an interface to change the strategy at any time.
        """
        self.strat = new_strat

    def how_fat( self ) :
        """
        Return the weight of the fat in the body part.
        """
        return self.strat( self.weight ) 

def skin_and_bones( weight ) :
    return weight * 0.02

def blubber( weight ) :
    return weight * 0.70

my_gut = BodyPart( 50 ) # you choose the units :-)
print my_gut.how_fat()
my_gut.change_strategy( skin_and_bones )
print my_gut.how_fat()
my_gut.change_strategy( blubber )
print my_gut.how_fat()



The body part itself doesn't know or care how the amount of fat is
determined.  It could be done by consulting an external measurement
device to get real world info on the fly, or it could be as simple as
the expressions above.

This particular incarnation of the Strategy pattern allows the
strategy of the object to be changed at any time.  Simply plug in a
new object that conforms to the interface (takes a numeric argument,
returns a numeric value, each with specified significance) and the
behavior of the object is changed.

Sometimes the object only allows specifying the strategy at creation
time.  For example I recently finished a project that took advantage
of Moshe Zadka's PMS framework.  He has a "Folder" class which has an
external storage ("Server", though it could be local disk) object to
manage the persistant storage of the messages.  There are also
"SortedFolder" and "LimitFolder" classes.  These classes follow the
Decorator pattern to decorate the base folder instance (basically they
wrap a "Folder", could be Sorted or Limited, and alter the view
clients have of the messages contained).  In addition they follow the
Strategy pattern : you pass in a function (at creation time) that
defines how the messages should be sorted or limited (filtered) and
the folder behaves that way.  Another [Sorted|Limit]Folder can be
instantiated with a different function plugged into it and it behaves
differently.  This makes it very easy to plug new functionality into
the system with little modification.

| | You want to know what the Composer instance is?  It is just an object. 
| | The fact that is uses composition instead of inheritance is mainly an
| | implementation detail.  Often times, though, composition is preferred 
| | over inheritance because it reduces icky inheritance trees.  In python,
| | composition is much easier since __getattr__ and __setattr__ 
| | can be written to automatically defer implementation to the internal 
| | objects without actually writing all the methods.
| 
| So, if an object is considered (or is focused, or concerned with) two
| different parts of two separate things, then I'd make a composite of the
two
| things?   I understand this concept in respect to multi part objects, but
| when it comes to something like a joint which isn't concerned with the
| entirety of the two objects that have come together, but the specific
points
| at which they come together and the functionality that arises out of such
a
| coupling, my mind seems a little fuzzy.
 
First you need to specify your goals.  Does this elbow exist solely to
connect the upper arm to the lower arm?  Does it server any other
purpose?  If not, then you can probably forget about it in your
program.  If you are trying to perform real-life simulations or
measurements then you will need it, and it will have the job of
allowing or preventing motion and have the potential to cause pain.

If you simply want to have a "person" then body parts are often
irrelevant -- you don't really need an arm to withdraw funds from your
bank account (simply invoke the right method).  However Quake would
look really funny if the characters had no arms.

When trying to model objects for a software system, consider the data
and the functionality the object will encapsulate.  Don't include it
just because the real world has it.  As Kirby said, objects (in a
computer) are just an illusion anyways (it's all the same bits in the
end, whether you use Python or ASM).

| I think I'll have to check out that design patterns book, I've heard it
| mentioned before!

You won't regret it!

-D


_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor