One module per class, bad idea?

E

Erik Johnson

There are arguments of preference to be made on both sides. I think the
question largely comes down to what is "workable" and "maintainable". To
answer the original question, I think it is not necessarily a bad idea to
have one class per file. But if your classes are small, or certain classes
are logically related to other classes (e.g., one class is a subclass of
another, or one class is implemented in terms of another, or the two classes
work together to accomplish some task and it wouldn't make much sense to be
using just one of the classes), it makes a lot of sense to keep them
together in the same file. If your classes are only a few dozen lines,
making lots of files may be more of a pain than having the code together in
one file.

Where I work, we started with a set of classes that provided a layer of
abstraction and encapsulation to accessing our database tables. An object
was basically just a loaded DB record and generally didn't provide a lot
else. As time went on, we started to code more and more logic into these
classes that provided various functions to make it easy to load records, do
certain kinds of computations and filtering with them, to generate the SQL
to do the insert for the record, etc.

The file has now grown into a 6800 line beast (including docstring,
whitespace, and CVS history). Pretty much any time we implement some new
functionality, there are at least a few changes in that file. When you have
multiple developers working on different projects, and they all need to be
making changes to that file, the chances for someone making a merge error
goes up. So, we are obviously at a point where that file needs to be split
up, but there are lots of other files that import and use the one file, so
it is a task that has been put off. In retrospect, I wish I has started
things under a one class per file strategy, but at the time, it didn't make
a lot of sense to split those things up and I didn't anticipate the code
getting that big.

So... there's no magic "one size fits all" answer here - do what makes
sense.

As Carl points out, decent editors should be able to handle dispaying
different files. I use vim and know I can split the window (both
horizontally and vertically), editing either different sections of the same
file or different files and can cut and paste between the two windows. In
practice, I usually just jump between places in the same file under a single
window, or I textually cut and paste between two separate vim sessions, but
if that's something you need to do a lot, you might want to invest a bit in
learning how to use split windows in your editor. Some of the documentation
for doing this under vim can be found here:
http://vimdoc.sourceforge.net/htmldoc/windows.html#:split and here:
http://vimdoc.sourceforge.net/htmldoc/usr_08.html
(I'm sure emacs can do this as well, but I don't know emacs.) If your
editor can't handle similar tasks, you might want to consider getting a
better editor.

HTH,
-ej
 
C

Carl Banks

Erik said:
The file has now grown into a 6800 line beast (including docstring,
whitespace, and CVS history). Pretty much any time we implement some new
functionality, there are at least a few changes in that file. When you have
multiple developers working on different projects, and they all need to be
making changes to that file, the chances for someone making a merge error
goes up. So, we are obviously at a point where that file needs to be split
up, but there are lots of other files that import and use the one file, so
it is a task that has been put off. In retrospect, I wish I has started
things under a one class per file strategy, but at the time, it didn't make
a lot of sense to split those things up and I didn't anticipate the code
getting that big.

Refactor NOW. I realize this is not as easy to do for a large team
than it is for a solo programmer like me, but ISTM people tend to
overestimate the cost and underestimate the benefit of it. And I've
seen some pretty bad excuses besides for not doing it. (But how can we
refactor when we have programmers checking stuff out all the time? Um,
how bout doing it during off hours? But it's too much to do in a
weekend! Which only goes to show you you've let it go too far.
Refactor in small doses.)

I have two files ~1000 lines that are marked as "these files are
getting too big". (They currently define 20 and 24 classes--though in
fairness the one with 24 has a bunch of small mixins.) Soon as this
overloaded holiday season is over, they're getting broken up.

So... there's no magic "one size fits all" answer here - do what makes
sense.

As Carl points out, decent editors should be able to handle dispaying
different files.

Actually, I pointed out that decent editors should be able to handle
displaying the same file twice. In case you want to edit two different
points of the same file side-by-side.


Carl Banks
 
P

Paddy

Carl said:
Refactor NOW.
Carl Banks
Are there tools out their to help with the refactoring task of
splitting a module into two or more sections then showing what other
files need to change?
 
G

Gabriel Genellina

It does make the imports look funny - I tend to give the module the same
name as the class, Java style, so I have
from foo.bar.MyClass import MyClass
but that is a minor point IMO.

You can always arrange things at the module level (inside
__init__.py) so from "outside", people can say:
from foo.bar import MyClass
if you consider MyClass being in its own module an implementation
detail that should be hidden.
<opinion class=personal>Module layout is an important design concept</opinion>


--
Gabriel Genellina
Softlab SRL






__________________________________________________
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
¡Probalo ya!
http://www.yahoo.com.ar/respuestas
 
G

Gabriel Genellina

Are there tools out their to help with the refactoring task of
splitting a module into two or more sections then showing what other
files need to change?

Usually no other files need to change. Ex: you have BigOldModule
including ClassA, ClassB and FunctionC. Move each one onto its own
module, perhaps including a subset of the original imports of BigOldModule.
Shrink BigOldModule to just:

from ClassA import ClassA
from ClassB import ClassB
from functionC import functionC

and maybe a few other things, so all imports from the outside remain
the same. That's all - most of the time.


--
Gabriel Genellina
Softlab SRL






__________________________________________________
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
¡Probalo ya!
http://www.yahoo.com.ar/respuestas
 
C

Carl Banks

Paddy said:
Are there tools out their to help with the refactoring task of
splitting a module into two or more sections then showing what other
files need to change?

I don't know what spiffy tools there are. If all I'm doing is moving a
class from one module to another, then a simple interactive search and
replace suffices for me; I modify import lines by hand.


Carl Banks
 
C

Carl Banks

Gabriel said:
Usually no other files need to change. Ex: you have BigOldModule
including ClassA, ClassB and FunctionC. Move each one onto its own
module, perhaps including a subset of the original imports of BigOldModule.
Shrink BigOldModule to just:

from ClassA import ClassA
from ClassB import ClassB
from functionC import functionC

and maybe a few other things, so all imports from the outside remain
the same. That's all - most of the time.

I wouldn't recommend this unless it's important not to change the
external usage. If you're doing it just to save work in refactoring,
it's a partial solution hack that'll lead to more confusion and delay a
real solution even more.


Carl Banks
 
G

Gabriel Genellina

I wouldn't recommend this unless it's important not to change the
external usage. If you're doing it just to save work in refactoring,
it's a partial solution hack that'll lead to more confusion and delay a
real solution even more.

In some cases you may consider the fact that ClassA is contained in
its own module, just an implementation detail, and not part of the
package public interfase.


--
Gabriel Genellina
Softlab SRL






__________________________________________________
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
¡Probalo ya!
http://www.yahoo.com.ar/respuestas
 
C

Carl Banks

Gabriel said:
In some cases you may consider the fact that ClassA is contained in
its own module, just an implementation detail, and not part of the
package public interfase.

Yes, I would say that falls under the "important not to change the
external usage" exception I gave.



Carl Banks
 
S

stdazi

Matias said:
I come from a background of Java and C# where it is common practise to have
one class per file in the file/project structure. As I have understood it,
it is more common practice to have many classes in a Python module/file.
What is the motivation behind it, would it be a bad idea to have a guideline
in your project that promotes a one class per file structure (assuming most
of the programmers a background similar to mine)?

IMO, even the Java practice is weird. I think classes should be split
into different files/modules due to their context and not their
number...
 
K

Kent Johnson

Carl said:
Man, I don't know you do it.

Say I'm sitting there concentrating on programming something, and I see
that I'll have to make a change in another file. All of a sudden, I
have to recall some filename out of thin air. Totally breaks my train
of thought, sometimes I space out trying to think of it because I have
to cold-start an entirely different part of my brain. It's less of a
mental distraction to just scroll.

But then to go back to where you were, you have to scroll back and find
your place. For me, just a click or keystroke to restore the last file
with the cursor or selection exactly where I left it. And if I am going
back and forth between the two, each switch is equally easy after the
first (opening the file).
(BTW, any decent editor will let you view different positions of the
same file side-by-side.)

Right, at a cost of showing you half as much of the one you care about.

Anyway, I'm not trying to convince anyone to change, just pointing out
that there are different styles of editing that make sense to those who
use them, if not to outside observers ;-)

Kent
 
C

Carl Banks

Kent said:
But then to go back to where you were, you have to scroll back and find
your place.

See, I find that to be a lot less of a mental disruption than recalling
a filename on the spot.
For me, just a click or keystroke to restore the last file
with the cursor or selection exactly where I left it. And if I am going
back and forth between the two, each switch is equally easy after the
first (opening the file).

Ok, but doesn't your editor have bookmarks? (I don't use them, because
remembering a bookmark name is the same mental disruption for me as
remembering a filename. Sometimes I use an interactive search will get
me to where I want to go if it's more than a screen or two.)
Right, at a cost of showing you half as much of the one you care about.

I presume if you're looking at two different files side-by-side it's at
the same cost?
Anyway, I'm not trying to convince anyone to change, just pointing out
that there are different styles of editing that make sense to those who
use them, if not to outside observers ;-)

That's fine; I'm not knocking anyone's style. But maybe you should
just leave it at, "I just prefer small files", and cease with the
editor-based arguments.

To be sure, there are probably editors out there that can load several
files into the same buffer, which would mean I could avoid recalling
filenames even when editing multiple files. (In fact, I think I'll
look for such a solution the next time I find myself editing Java.)
It's really not about the editor; I just think that the module is the
best place for higher-level organization.

But the package will do.


Carl Banks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top