[Tutor] Modifying Source Code while Program is Running

Alan Gauld alan.gauld at freenet.co.uk
Sun Nov 27 10:03:08 CET 2005


> However, I'm still slightly uncomfortable with it.  It smells to me a
> bit like the "as long as it works, its fine" school of thought.

FRom the client point of view thats true, but from the class designers
point of view its very important that the internals be we well designed.
And that includes how the internal objects and ultimately data are
represented, but its a much smaller (and therefore easier) problem
than trying to solve the total data picture. In this regard objects are
an abstraction layer on top of the data, we focus on the entities
and let the fields take care of themselves (or let the entity designers
do it for us!)...

> defined, as at the end of the day it's the data that matters

Only at one level. You are right that the inputs and outputs of a
program will be expressed in terms of data, but the program itself
is an expression of behaviour. If I feed this in you transform it to
that out. You can feed the data in as one big tuple ands feed it
out in the same way, what happens to it in between is not important
so long as the output is correctly matched to the input.

> data is given to me by other people and can rarely be gotten back).

The trick is not to change the inpuit data but to generate new output
from the input. This is standard functional programming practice and
good to apply in procedural, OOP or functional programming styles.

>> Whereas in OOP you simply say
>
>> obj.doThing()
>>
> But writing a different doThing() for each object can be a huge waste
> of time.  You want to be able to write one doThing() that is going to
> work on each object (of a particular type).  This requires either
> knowing that all your objects are going to be similar in some respect,
> or writing a huge if..elseif as you mentioned.

On the contrary its nearly alwys more efficient to write a separate
function that gets called polymorphically than have long if/else chains.
Not least because:
a) you wind up with lots of if/else chains - one for every invocation
of the polymorphic method
b) the if/elif chains become a big maintenance headache requiring a
revisit to each one every time you introduce a new type
c) the invoking function becomes vulnerable to changes in the internals
of the called objects, introducing high levels of coupling which is "a bad 
thing"

Avoiding these kinds of chained if/else structures is one of the primary
goals of good OO design, and one of the biggest improvements in reliability
and readability brough about by OOP. But it does require a wee bit of faith
initially to trust it! :-)

However the many functions are not as bad as they sound because
you don't have to write the whole function out again, only the differences.
For example:

class C:
     # some data bits here...
    def doit(self)
          # process the data bits
          pass

class D(C):
    # some new data bits here
    def doit(self):
         C.doit(self)    # get C to do its bits first
         # process my data bits
         pass

class E(D):
    # data
    def doit(self):
         D.doit(self)
         # do my data bits
        pass

So each subclass only has to process its own data and
call the superclass method. The superclass call can be at the start,
end or in the middle of the method - in Lisp terms this is called
BEFORE, AFTER and AROUND methods...

And if you think about it the data all has to be handled anyway
so the extra lines of code is actually very few, much fewer than
the accumulation of multiple if/else chains, and much easier to
maintain because each object is responsible for its own data
and nobody elses!

> Even just saying every object has a doThing() is starting
> to create a data structure.

No its creating a behaviour structure, the two things are very
different. Data structures are by definition static, behavour
stuctures are dynamic. It is the difference between static
data structures and dynamic behaviour structures that gives
OOP its power. Every time you rely on a static data structure
within an object you are limiting its ability to be reused.

>> But that's behaviour of the Page, just let it create its own form
>> and do its own searches, not your problem. Create the right
>> kind of Page and it will do the work for you...
>
> But then I've got to create lots of different behaviours instead of
> one simple generalised behaviour.

Correct, thats what OOP is all about, lots of very short simple,
(and thus reliable) methods. But you can parameterise them
but often thats doine by passing other objects with their own
behaviour. Thus

class C:
    def meth(self, startObj, endObj)
        startObj.doit()
        doSomeOtherStuff()
        endObj.finish()

So by passing in different objects we can completely change
the behaviour of meth, but not by relying on data just passing
in the objects we are working with andletting them do whatever
it is they do...

> > So maybe attributes are objects too? Maybe you page needs
>> to know how to handle attributes and you can create pages by

>This combined with what Kent said, is what really solved the problem for 
>me.

Yes, you do have to keep stopping and asking "should this be an object?"
Of course you can go too far and make everything an object until you
wind up recreating the wheel (or the string, int etc). Part of the challenge
of OOP is to know when you've hit the bottom of the tree!

Picking up Kent's message about refactoring, my approach tends to
mean I more often refactor by combining classes into a higher level one,
or reverting a class to a native data type than I do by breaking a class
into smaller pieces. Most folks tend to mean the opposite direction
when they say refactor - breaking a class or method out into two.

> I've really gained a huge amount just from this one topic.  Not least
> of which is that classes aren't necessarily a good answer to OOP
> problems.

Well classes are pretty essential! But thinking about the right granularity
is important, and that classes should be as small as possible, but no 
smaller...

> I know that such a thing could be invented.  It's very
> straightforward, it's just a lot of work.

The problem is its not straightforward at all. People have been trying
to build such dynamic environments for the last 50 years. 
Millions(BIllions?)
of dollars have been spent and untold manhours but its very very difficult.
As someone who once spent 5 years on a project trying to do something 
similar,
working with some very clever people, I've come to the conclusion that
it will take a radical change in the way we build computers before that
kind of environment is truly available.

But I'd love to be proved wrong! :-)

Alan G
Author of the learn to program web tutor
http://www.freenetpages.co.uk/hp/alan.gauld




More information about the Tutor mailing list