By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,941 Members | 1,789 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,941 IT Pros & Developers. It's quick & easy.

software design question

P: n/a
Hi,

I have the following inter-class relationships:

__main__: (in file LMCMain.py)
imports module FileIO
defines class LMCMain
instanciats main = LMCMain(...)

FileIO.py:
defines class FileIO
class FileIO needs to access "main" from LMCMain.py

In FileIO.py I've tried to "import LMCMain", but that causes the main
program to be re-executed. I only wanted to access to the main class
instance LMCMain.
My aim is a modular software design. I know this yields much communication
overhead and may become compilcate soon. Here I rely on "its not too slow"
and eventually perhaps psyco.

A solution I could think of would be a Singleton. Both LMCMain.py and
FileIO.py import "singleton.py". LMCMain.py stores "main" in singleton and
FileIO.py accesses it.
I could also use a static class instead of a public module variable... I
don't really know whats better.

I'd like to fall back on some design pattern, but somehow you can only use
them, once you're used to them (i.e. theoretical knowledge does not
suffice).
I also learned much from the "logging" module and the Qt SIGNAL-SLOT concept
which IMO are excellently designed.

I know this is not strictly related to Python, but since I'm working in
Python I'd like to hear pythoneers suggestion to it.

Thanks in advance
Uwe
Jul 18 '05 #1
Share this Question
Share on Google+
24 Replies


P: n/a
> I have the following inter-class relationships:

__main__: (in file LMCMain.py)
imports module FileIO
defines class LMCMain
instanciats main = LMCMain(...)

FileIO.py:
defines class FileIO
class FileIO needs to access "main" from LMCMain.py


I don't know what one /should/ call it, but what you have is what I
would call a circular import. You are attempting to have two modules
use the internals of each other. That is poor design.

You can use a kludge to get past poor design by using the following:

main = LMCMain()
import sys
sys.modules['FileIO'].main = main
In the future, better design is suggested.

- Josiah
Jul 18 '05 #2

P: n/a
Josiah Carlson wrote:
I don't know what one /should/ call it, but what you have is what I
would call a circular import. You are attempting to have two modules
use the internals of each other. That is poor design.
[...kludge...] In the future, better design is suggested.


Ok, the following is the case:
I got a GUI. This is the base class (automatically generated) from which i
derive a class that does the implementation. However, since that may become
rather big I devided the functionality into different modules, i.e. one for
presentation, one for file-IO, one for help-topic related stuff, etc.
So this main file imports the modules that implement the functionality.
Obviously these modules need to access things like "enable action"s, install
hooks, etc. from the "main part".
And thats why the circular dependency.

I know that circular dependencies are rather bad than helpful, but the only
way to circumvent this is to build everything into one big block - which I
find is rather worse: the source file grows much too large to maintain a
good overview.

So the question is rather: how to make a better design?

Ciao
Uwe
Jul 18 '05 #3

P: n/a
> So the question is rather: how to make a better design?

import module1
....

class main:
def __init__(self, args...):
self.c1 = module1.class1(args...)
#where args... is the standard initialization for your class,
# and any additional objects/methods that c1 needs
# access to.

Pass what is needed. If you can't pass what is needed when external
module classes are initialized, then set the attribute later.

c1instance.attribute = value

- Josiah
Jul 18 '05 #4

P: n/a
>
Ok, the following is the case:
I got a GUI. This is the base class (automatically generated) from which i
derive a class that does the implementation. However, since that may become
rather big I devided the functionality into different modules, i.e. one for
presentation, one for file-IO, one for help-topic related stuff, etc.
So this main file imports the modules that implement the functionality.
Obviously these modules need to access things like "enable action"s, install
hooks, etc. from the "main part".
And thats why the circular dependency.

I know that circular dependencies are rather bad than helpful, but the only
way to circumvent this is to build everything into one big block - which I
find is rather worse: the source file grows much too large to maintain a
good overview.

So the question is rather: how to make a better design?

Why not look at the GUI as a "presentation layer" that provides access
to the program functionality, like file I/O, help access, etc. Then the
file I/O, help, (etc...) can be written without any knowledge to the GUI
(and therefore testable from a python shell or a testing script) and the
Gui code just call the File I/O, help functions or members. If you need
callbacks, then provide callbacks. This way you would decouple the
GUI from the system functionality. Only GUI code would import the other
modules. The File I/O, help (etc...) would not know anything about the
GUI implementation requirements.

Hope that helps,

Pierre

Jul 18 '05 #5

P: n/a
Pierre Rouleau wrote:
So the question is rather: how to make a better design?


Why not look at the GUI as a "presentation layer" that provides access
to the program functionality, like file I/O, help access, etc. Then the
file I/O, help, (etc...) can be written without any knowledge to the GUI
(and therefore testable from a python shell or a testing script) and the
Gui code just call the File I/O, help functions or members. If you need
callbacks, then provide callbacks. This way you would decouple the
GUI from the system functionality. Only GUI code would import the other
modules. The File I/O, help (etc...) would not know anything about the
GUI implementation requirements.


I've already got separate modules for non-GUI related functionalities, i.e.
accessing record based file formats, etc. These are imported by the module
that currently covers "Open", "Save", "Save As", "Properties", "New" (in
the File menu).
This alone spans 442 lines (including comments and empty lines), containing
only dialog interaction and calls to the previously mentioned file-module.

Is 500 lines a good count to start splitting up the code?

Currently the "main" part is just a main widget with all its toolbars, menu-
and status bar. This part imports all other modules that then cover a small
portion of the programs functionality, i.e. one module covers all file
open, save, close related stuff, another may cover all help related
actions, another covers the presentation, modification and propagation of
the rather large collection of preferences, etc.

My current solution is thinking along the line that all these components
usually exist only once in the system, i.e. there's no reason why there
should be two objects covering the same preferences dialog.
So each component implements the list or dictionary interface by which its
data can can be accessed from other components. For example after opening a
file an access to the fileIO component like: fileIO[0:10]
would return the first 10 records from the file.
Similarly something like preferences['fileIO'] might return all preferences
for the fileIO component, etc.
Of course the component that displays the record (presentation layer) will
need to be notified of a new file that has been loaded. To realise this I
have implemented a "callback" mechanisme similar to the Qt's SIGNAL-SLOT
mechanisme: the fileIO component registers signals "fileNew", "fileOpen",
etc. under the name 'fileIO'. And when a component wants to be notified
when a new file is opened it sort of 'fileIO.registerCallback("fileNew()",
self.fileNew_callback)'.
And then the fileIO module calls all callbacks in the list of "fileNew()"
when a new file has been opened.

Is this approach getting to complicated?

One problem I'm still having with this is: for component B to register a
callback at component A, B still got to have a reference to component A in
order to make a call like "A.registerCallback(...)"
You might not know what B needs to access, so you cannot pass "what is
needed" in the constructor, nor let the code that instanciates B set
attributes.

Ciao
Uwe
Jul 18 '05 #6

P: n/a
Josiah Carlson wrote:
So the question is rather: how to make a better design? [...]
Pass what is needed. If you can't pass what is needed when external
module classes are initialized, then set the attribute later.

c1instance.attribute = value


Ok, that is a way of enabling the circular dependency, but that doesn't
really get rid of it. The main program still needs the module and the
module may now access parts from the main program using the passed
parameters or the later set attributes.

That was my first approach, passing what's needed. But if module1 delegates
some task to another module, then again all args must be passed to that
module and so forth.
Now currently I've got about 7 such modules that may need to interact then I
end up in passing to each level of delegation an increasingly _huge_
parameter list and that's where I stopped thinking in that direction.

My current solution to this is to pass the instances that may need to be
publicly known as value in a key:value pair, stored in a dictionary. Thus
something like:
import singleton
single = singleton.Singleton()
single['main']


returns the appropriate instance.

Ciao
Uwe
Jul 18 '05 #7

P: n/a
"Uwe Mayer" <me*****@hadiko.de> wrote in message
news:c0**********@news.rz.uni-karlsruhe.de...

One problem I'm still having with this is: for component B to register a
callback at component A, B still got to have a reference to component A in
order to make a call like "A.registerCallback(...)"
You might not know what B needs to access, so you cannot pass "what is
needed" in the constructor, nor let the code that instanciates B set
attributes.
I suspect you've got the callback logic backwards. The basic
layering pattern is "call down, notify up," and it's the upper layer's
responsibility to request the notification.

To explicate: the GUI module calls the domain
module for service. It also calls the domain module
to register callbacks, passing the function that it
want's called.

When the domain layer has something it wants to
tell the GUI layer, it simply runs a (possibly empty)
list of callback functions.

John Roth

Ciao
Uwe

Jul 18 '05 #8

P: n/a
From the sounds of your posts, you want your software to be "modular",
in that you want have one file for each of the different components, but
you don't want to spend the time to pass down all the proper references.
As a result, you want to have a single global namespace for all of
your modules, so that you don't have to pass anything down.

There is another kludge:
#main.py
import x
import y

#make a copy of the dictionaries so that
xold = dict(x.__dict__)
yold = dict(y.__dict__)
x.__dict__.update(yold)
y.__dict__.update(xold)

x.xrunme()
y.yrunme()

#x.py
def xrunme():
print "calling yrunyou"
yrunyou()

def xrunyou():
print "called xrunyou"

#y.py
def yrunme():
print "calling xrunyou"
xrunyou()

def yrunyou():
print "called yrunyou"
In the above, you don't even need to import the sibling modules.
Believe it or not, it works.

I would suggest you just put everything into a single file. 500 lines
is not that large. Heck, a few thousand isn't even that bad, as long as
you pay attention to what you are doing and use an editor with a
browsable source tree/class heirarchy, and comment liberally.

- Josiah

P.S. For more stuff on this topic, check the thread with subject "Basic
'import' problem", which has the same subjects pop up.
Jul 18 '05 #9

P: n/a
Josiah Carlson wrote:
From the sounds of your posts, you want your software to be "modular",
in that you want have one file for each of the different components, but
you don't want to spend the time to pass down all the proper references.
As a result, you want to have a single global namespace for all of
your modules, so that you don't have to pass anything down.
Almost. I want to write software from components. I want a simple, yet clear
and effective interface for the components to communicate with eachother.
The components will be dynamically loaded. If available they have to fit
like a piece in a puzzle, if ther're unavailable all related functionality
will be unavailable - *not* raise exceptions or cause program abortion,
etc.

I simply cannot pass all components to all others, because I don't yet know
which components there might be.

Having a single global name space is poor software design. It makes you not
having to think about "inter module communication", because there is none
to take care of, because you can call virtually everything from everywhere.
There is another kludge: [...] I would suggest you just put everything into a single file. 500 lines
is not that large. Heck, a few thousand isn't even that bad, as long as
you pay attention to what you are doing and use an editor with a
browsable source tree/class heirarchy, and comment liberally.


Wow! You can't seriously suggest this as a software design recommendation!

Importing the complete namespace from one module into another is exactly
what will cause you fourty hours of debugging code afterwards.

Do you think there is a reason why in Java every class got to be put into
one source file - or is this just a bad language restriction?
Don't get me wrong, I'm not critisizing Python here.

Searching the litherature I found the following on how to model interaction
between modules:

- relations between modules should be hierachial, i.e. non-cyclic

problem with circular dependencies: "nothing works until everything works"

benefits of non circular design:
1. development and testing step by step is possible,
2. you can build subsets for
- use in other systems
- own re-use

*sandwiching*:

cyclic dependencies may be resolved by refining the modular structure:

A <==> B

Suggestion 1:

A1 ==> B ==> A2
A1 ========> A2

Suggestion 2:

A2 ==> B2 ==> A1 ==> B1
A2 =========> A1 B1
B2 =========> B1

Ciao
Uwe
Jul 18 '05 #10

P: n/a
"Uwe Mayer" <me*****@hadiko.de> wrote in message
news:c0**********@news.rz.uni-karlsruhe.de...
Josiah Carlson wrote:
From the sounds of your posts, you want your software to be "modular",
in that you want have one file for each of the different components, but
you don't want to spend the time to pass down all the proper references.
As a result, you want to have a single global namespace for all of
your modules, so that you don't have to pass anything down.
Almost. I want to write software from components. I want a simple, yet

clear and effective interface for the components to communicate with eachother.
The components will be dynamically loaded. If available they have to fit
like a piece in a puzzle, if ther're unavailable all related functionality
will be unavailable - *not* raise exceptions or cause program abortion,
etc.

I simply cannot pass all components to all others, because I don't yet know which components there might be.

Having a single global name space is poor software design. It makes you not having to think about "inter module communication", because there is none
to take care of, because you can call virtually everything from everywhere.
There is another kludge: [...]
I would suggest you just put everything into a single file. 500 lines
is not that large. Heck, a few thousand isn't even that bad, as long as
you pay attention to what you are doing and use an editor with a
browsable source tree/class heirarchy, and comment liberally.


Wow! You can't seriously suggest this as a software design recommendation!

Importing the complete namespace from one module into another is exactly
what will cause you fourty hours of debugging code afterwards.

Do you think there is a reason why in Java every class got to be put into
one source file - or is this just a bad language restriction?
Don't get me wrong, I'm not critisizing Python here.

Searching the litherature I found the following on how to model

interaction between modules:

- relations between modules should be hierachial, i.e. non-cyclic

problem with circular dependencies: "nothing works until everything works"

benefits of non circular design:
1. development and testing step by step is possible,
2. you can build subsets for
- use in other systems
- own re-use

*sandwiching*:

cyclic dependencies may be resolved by refining the modular structure:

A <==> B

Suggestion 1:

A1 ==> B ==> A2
A1 ========> A2

Suggestion 2:

A2 ==> B2 ==> A1 ==> B1
A2 =========> A1 B1
B2 =========> B1
As I suggested in another post, this doesn't always work in practice.
Another term for hierarchical design is layered architecture. The
rule in a layered architecture is "call down, notify up." It's the higher
layer's responsibility to call down to install callbacks so that the
lower layer can notify up at run time.

What makes this work is that the notifier on the lower layer
can't depend on there being any callbacks installed. In other
words, it should be able to do whatever it does if nobody
is listening.

John Roth
Ciao
Uwe

Jul 18 '05 #11

P: n/a
Uwe Mayer <me*****@hadiko.de> wrote in message news:<c0**********@news.rz.uni-karlsruhe.de>...
Almost. I want to write software from components.
Components must try to reduce their dependencies. So your design may
not be the best one.
Having a single global name space is poor software design.
No absolutely not. There are Programs with millions of lines written
in C that are good designed and reliable software.
Having a common prefix is nothing else then using namespaces.
Do you think there is a reason why in Java every class got to be put into
one source file - or is this just a bad language restriction?


This has to do with dynamic loading. Nothing else.
But maybe more constructive:

In my software (Eiffel) i have a CORE_MANAGER class that has objects
like EDITOR, COMPILER etc. This are facade patterns to the
subsystems. I also have EDITOR_BRIDGE, COMPILER_BRIDGE classes. The
editor provides its functionality to the outside world only with this
class and can use only the services found in the EDITOR_BRIDGE object.

The CORE_MANAGER class now sets up the editor or some editor mock
object if the editor is not used.

This requires quite a lot of glue code but i'm now able to switch
independent subsystems on and off. So i could split my 250.000 lines
program into 8 optional subsystems.
Jul 18 '05 #12

P: n/a
Uwe Mayer <me*****@hadiko.de> wrote in message news:<c0**********@news.rz.uni-karlsruhe.de>...
Pierre Rouleau wrote:
So the question is rather: how to make a better design?


Why not look at the GUI as a "presentation layer" that provides access
to the program functionality, like file I/O, help access, etc. Then the
file I/O, help, (etc...) can be written without any knowledge to the GUI
(and therefore testable from a python shell or a testing script) and the
Gui code just call the File I/O, help functions or members. If you need
callbacks, then provide callbacks. This way you would decouple the
GUI from the system functionality. Only GUI code would import the other
modules. The File I/O, help (etc...) would not know anything about the
GUI implementation requirements.


I've already got separate modules for non-GUI related functionalities, i.e.
accessing record based file formats, etc. These are imported by the module
that currently covers "Open", "Save", "Save As", "Properties", "New" (in
the File menu).
This alone spans 442 lines (including comments and empty lines), containing
only dialog interaction and calls to the previously mentioned file-module.

Is 500 lines a good count to start splitting up the code?


No !
My modules are normally between 1000-3000 lines. Having to much files
(worst case scenario is PHP) is just another form of spaghetti code.
With so small files you should focus on the task that needs to be done
and only if you really do two different things in one module you
should decide to split it. Maybe a merge would help you more then
splitting.
Jul 18 '05 #13

P: n/a
> Almost. I want to write software from components. I want a simple, yet clear
and effective interface for the components to communicate with eachother.
The components will be dynamically loaded. If available they have to fit
like a piece in a puzzle, if ther're unavailable all related functionality
will be unavailable - *not* raise exceptions or cause program abortion,
etc.
Design your interface, and write your program around your interface.
Here's one:

#main
import submodule

class data_storehouse:
pass

passer = data_storehouse()
passer.error = None
passer.main = main
#etc.

def caller(*args, **kwargs):
passer.args = args
passer.kwargs = kwargs

submodule(passer)
if passer.error:
#handle the error
This is essentially another user was doing with their "Singleton()"
interface, though they created a bottom-level module to hold all
application-wide information.

I simply cannot pass all components to all others, because I don't yet know
which components there might be.
So you only pass the ones you know about when writing your application.
When functionality A gets created, before component B, likely
functionality A won't require component B. If you discover later that
it does, then you modify functionality A to use component B. You can't
magically get away from this.

Having a single global name space is poor software design. It makes you not
having to think about "inter module communication", because there is none
to take care of, because you can call virtually everything from everywhere.
Of course it is. It also doesn't scale very well, though Python
namespaces (dictionaries) don't seem to have issues with pollution, it
can get unweidly to handle.

There is another kludge:


[...]
I would suggest you just put everything into a single file. 500 lines
is not that large. Heck, a few thousand isn't even that bad, as long as
you pay attention to what you are doing and use an editor with a
browsable source tree/class heirarchy, and comment liberally.


Wow! You can't seriously suggest this as a software design recommendation!


The kludge, no. That's why I called it a kludge. You can propagate
namespaces without a problem, and you don't even have to worry about the
Python import mechanisms. It ends up with the same functionality as
having a single module, without having a single module.

Importing the complete namespace from one module into another is exactly
what will cause you fourty hours of debugging code afterwards.
I never said it was a good idea.

Do you think there is a reason why in Java every class got to be put into
one source file - or is this just a bad language restriction?
Don't get me wrong, I'm not critisizing Python here.
I don't know, I never thought about it, because I never learned Java. I
was in the last year they taught C/C++.

Thinking about it now, I think it is a poor language restriction. Being
able to have a half-dozen classes with related functionality in a single
module is /very/ convenient. Check out the threading or itertools
modules. Imagine having to use threading.Thread.Thread or
itertools.imap.imap, those would be annoying and useless bubbles.
A <==> B

Suggestion 1:

A1 ==> B ==> A2
A1 ========> A2

Suggestion 2:

A2 ==> B2 ==> A1 ==> B1
A2 =========> A1 B1
B2 =========> B1


You can still end up SOL if A1 requires functionality from A2. You
still have a circular dependency. As the sibling reply by John Roth says,
"this doesn't always work in practice. Another term for hierarchical
design is layered architecture. The rule in a layered architecture is
'call down, notify up.' It's the higherlayer's esponsibility to call
down to install callbacks so that the lower layer can notify up at
run time."

John says the truth.
- Josiah
Jul 18 '05 #14

P: n/a
On Sunday 08 February 2004 01:24 John Roth wrote in
<10*************@news.supernews.com>:
I suspect you've got the callback logic backwards. The basic
layering pattern is "call down, notify up," and it's the upper
layer's responsibility to request the notification.

To explicate: the GUI module calls the domain
module for service. It also calls the domain module
to register callbacks, passing the function that it
want's called.

When the domain layer has something it wants to
tell the GUI layer, it simply runs a (possibly empty)
list of callback functions.


Can you exemplify it?

I'm very interested on such approach and I'm going to read a little
more about it, but examples in Python would help a lot.
TIA,
--
Godoy. <go***@ieee.org>
Jul 18 '05 #15

P: n/a

"Jorge Godoy" <go***@ieee.org> wrote in message
news:l6************@wintermute.g2ctech...
On Sunday 08 February 2004 01:24 John Roth wrote in
<10*************@news.supernews.com>:
I suspect you've got the callback logic backwards. The basic
layering pattern is "call down, notify up," and it's the upper
layer's responsibility to request the notification.

To explicate: the GUI module calls the domain
module for service. It also calls the domain module
to register callbacks, passing the function that it
want's called.

When the domain layer has something it wants to
tell the GUI layer, it simply runs a (possibly empty)
list of callback functions.
Can you exemplify it?

I'm very interested on such approach and I'm going to read a little
more about it, but examples in Python would help a lot.


A simple notify class:
---------------------------------------------
class Notify(object):
def __init__(self):
self.listenerList = []

def sendMessage(self, event):
for callback in self.listenerList:
callback(event)
return

def addListener(self, callback):
self.listenerList.append(callback)

def removeListener(self, callback):
self.listenerList.remove(callback)
---------------------------------------------

Here's a place where I instantiate it:

--------------------------------------------------------------
class ALocation(object):
def __init__(self):
self._latitude = LatitudeContainer()
self._longitude = LongitudeContainer()
self._placeName = StringContainer()
self._titleNotifier = A4Base.Notify.Notify()
self._latitude.addListener(self._titleUpdated)
self._longitude.addListener(self._titleUpdated)
---------------------------------------------------------------

and the routine that uses this notifier:

--------------------------------------------------------
def _titleUpdated(self, event):
self._titleNotifier.sendMessage(event)
--------------------------------------------------------

LatitudeContainer and LongitudeContainer both derive
from BaseContainer (through StringContainer, but that
doesn't add anything to this example):

-------------------------------------------------------
class BaseContainer(object):
def __init__(self):
self._notifier = A4Base.Notify.Notify()
def addListener(self, callback):
return self._notifier.addListener(callback)
def removeListener(self, callback):
return self._notifier.removeCallback(callback)
def _sendMessage(self, message):
return self._notifier.sendMessage(message)
---------------------------------------------------------

here's the routine in LatitudeContainer that fires
off the notification:

------------------------------------------------------
def _setStringValue(self, value):
self.parseLat(value)
if self._stringValue != value:
self._stringValue = value
self._sendMessage(value)
-------------------------------------------------------

HTH

John Roth


TIA,
--
Godoy. <go***@ieee.org>

Jul 18 '05 #16

P: n/a
On 8 Feb 2004 08:18:06 -0800, ll*****@web.de (Lothar Scholz) wrote:
Uwe Mayer <me*****@hadiko.de> wrote in message news:<c0**********@news.rz.uni-karlsruhe.de>...
Do you think there is a reason why in Java every class got to be put into
one source file - or is this just a bad language restriction?


This has to do with dynamic loading. Nothing else.


It might have something to do with something else, since it is a false
statement, not a language restriction:
---------- cut here ----------
// multiclass.java
// demonstrates two classes in one source file.

class multiclass
{
public static void main(String args[])
{
System.out.println(bork.bork());
}
}

class bork
{
public static String bork()
{
return "Bork!";
}
}
---------- ereh tuc ----------

--dang
Jul 18 '05 #17

P: n/a
Lothar Scholz wrote:
Is 500 lines a good count to start splitting up the code?

No !
My modules are normally between 1000-3000 lines. Having to much files
(worst case scenario is PHP) is just another form of spaghetti code.
With so small files you should focus on the task that needs to be done
and only if you really do two different things in one module you
should decide to split it. Maybe a merge would help you more then
splitting.


What IDE /Editor do you use? I currently use Emacs and I find it very hard
to skip back and forth between methods and functions in larger files.

Ciao
Uwe
Jul 18 '05 #18

P: n/a
No !
My modules are normally between 1000-3000 lines. Having to much files
(worst case scenario is PHP) is just another form of spaghetti code.
With so small files you should focus on the task that needs to be done
and only if you really do two different things in one module you
should decide to split it. Maybe a merge would help you more then
splitting.

What IDE /Editor do you use? I currently use Emacs and I find it very hard
to skip back and forth between methods and functions in larger files.


I would imagine he uses his own editor: http://www.python-ide.com

I also don't have any issues editing 1-3k line files using my own
editor: http://pype.sourceforge.net (PyPE itself is ~3900 lines).

I believe the major difference, at least in terms of scalability, has to
do with the existance of a browsable source tree (aka a class browser).
It has helped me significantly.

- Josiah
Jul 18 '05 #19

P: n/a
ll*****@web.de (Lothar Scholz) wrote in message news:<6e**************************@posting.google. com>...
Is 500 lines a good count to start splitting up the code?


No !
My modules are normally between 1000-3000 lines. Having to much files
(worst case scenario is PHP) is just another form of spaghetti code.


Oh! As a comparison, my modules are typically 100-200 lines long. I don't
feel they are spaghetti, since they are collected in directories with
well chosen names and/or in packages. Also, they are typically intended
to be reusable. Moreover, I feel much easier to edit simultaneously
three or four buffers than to navigate back and forth on a very long single
buffer. Finally, I don't want to be too dependent on the editor features, so
small modules are a win should I need to use Notepad (God save me! ;)

P.S. once I computed the average lenght of modules in the standard library.
The result was something like 200 lines.

Michele Simionato
Jul 18 '05 #20

P: n/a
> Moreover, I feel much easier to edit simultaneously
three or four buffers than to navigate back and forth on a very long single
buffer.
Depending on the features of your editor, going to different locations
in the current buffer (even offset by many lines) can be arbitrarily
trivial. When you have a source tree, you are a double-click away from
any class/function/method (or even properly-formed comments, depending
on the editor support). For those cases when keyboards shortcuts are
convenient, some editors have per-line bookmarks that allow you to hop
to often-used code portions very quickly.

I'm sure all of this can be done with Emacs (perhaps even Vim), if you
know how to do it.

P.S. once I computed the average lenght of modules in the standard library.
The result was something like 200 lines.


Sounds like a histogram is in order. Maybe I'll do it this weekend when
I have the time.

- Josiah
Jul 18 '05 #21

P: n/a
Josiah Carlson wrote:
What IDE /Editor do you use? I currently use Emacs and I find it very
hard to skip back and forth between methods and functions in larger
files.
I would imagine he uses his own editor: http://www.python-ide.com

I also don't have any issues editing 1-3k line files using my own
editor: http://pype.sourceforge.net (PyPE itself is ~3900 lines).


I did some browsing and found another, quite nice one:
http://www.die-offenbachs.de/detlev/eric3.html

For small programs its the total overkill. It may be more usefull if you're
developing graphical programs, since it supports compiling Qt .ui files,
got some menubar entries for Qt Reference Manual, QLinguist,
QXXXDialog-Wizards, etc. (if you happen to like that sort of editor).

Nice features I found include:
- Unittest support (i.e. for rapid prototyping)
- refactoring tools
I believe the major difference, at least in terms of scalability, has to
do with the existance of a browsable source tree (aka a class browser).
It has helped me significantly.


What I am missing includes:
- browsable source tree :(
- Emacs's comment-box
- Emacs keyboard shortcuts

If there anybody knows some other nice Editors you know, I'd like to know
about them.

Ciao
Uwe
Jul 18 '05 #22

P: n/a
>>I would imagine he uses his own editor: http://www.python-ide.com

I also don't have any issues editing 1-3k line files using my own
editor: http://pype.sourceforge.net (PyPE itself is ~3900 lines).
I did some browsing and found another, quite nice one:
http://www.die-offenbachs.de/detlev/eric3.html

For small programs its the total overkill. It may be more usefull if you're
developing graphical programs, since it supports compiling Qt .ui files,
got some menubar entries for Qt Reference Manual, QLinguist,
QXXXDialog-Wizards, etc. (if you happen to like that sort of editor).


Yeah, I found Eric3 a while ago as well. My one problem is that I
couldn't get it to work with windows, every binary for QT that I tried
didn't want to work.
What I am missing includes:
- browsable source tree :(
- Emacs's comment-box
- Emacs keyboard shortcuts


Eric3 doesn't have a browsable source tree?

There is an editor called SPE (Stani's Python Editor). It has comments
and a browsable source tree. I don't know if it has the keyboard
shortcuts. One thing that stops me from using it (as opposed to my own
editor) is that it is really slow. Start messing around with multiple
buffers, or files larger than a few hundred lines. Ick.

- Josiah

Jul 18 '05 #23

P: n/a
On Tue, 10 Feb 2004 23:47:12 -0800, Josiah Carlson <jc******@nospam.uci.edu> wrote:
Moreover, I feel much easier to edit simultaneously
three or four buffers than to navigate back and forth on a very long single
buffer.


Depending on the features of your editor, going to different locations
in the current buffer (even offset by many lines) can be arbitrarily
trivial. When you have a source tree, you are a double-click away from
any class/function/method (or even properly-formed comments, depending
on the editor support). For those cases when keyboards shortcuts are
convenient, some editors have per-line bookmarks that allow you to hop
to often-used code portions very quickly.

I'm sure all of this can be done with Emacs (perhaps even Vim), if you
know how to do it.

P.S. once I computed the average lenght of modules in the standard library.
The result was something like 200 lines.


Sounds like a histogram is in order. Maybe I'll do it this weekend when
I have the time.

A quick data point:
import os
wc = os.popen(r'wc D:\Python23\Lib\*py').readlines()
sum([int(x.split()[0]) for x in wc[:-1] if x])/float(len(wc)-1) 412.61621621621623 print wc[-1]

76334 250898 2657018 Totals

Gotta go...

Regards,
Bengt Richter
Jul 18 '05 #24

P: n/a
> A quick data point:
>>> import os
>>> wc = os.popen(r'wc D:\Python23\Lib\*py').readlines()
>>> sum([int(x.split()[0]) for x in wc[:-1] if x])/float(len(wc)-1) 412.61621621621623 >>> print wc[-1]

76334 250898 2657018 Totals

Gotta go...


I'm going to have to remember wc. That is sweet.

- Josiah
Jul 18 '05 #25

This discussion thread is closed

Replies have been disabled for this discussion.