Spreading a class across several compilation units

M

Matthias Kaeppler

Hello,

this more a question about good practice than it is about the C++
language itself, but still... my question is this:

I have a class representing the main window of my application which is
really growing big. Well, most of the action is happening in the main
window in my app so that's okay I guess. To solve the clutter, I thought
about splitting up the class into several smaller ones, but that didn't
feel right, mainly because it would have gone along with an increase of
complexity (further interaction would be needed between several classes)
which just isn't worth it.

Now my other idea was to group functions which share certain semantics
(e.g. signal handlers) into separate compilation units. However, this
would mean breaking up the class and spreading it over several files. I
had a look at the Nautilus source code, and that's how they do it and I
think it's a really good approach, but it's written in C afterall, so
I'm not sure if that applies to C++ as well.

Is that bad practice in C++? What would you do instead?

Regards,
Matthias Kaeppler
 
V

Victor Bazarov

Matthias said:
this more a question about good practice than it is about the C++
language itself, but still... my question is this:

I have a class representing the main window of my application which is
really growing big. Well, most of the action is happening in the main
window in my app so that's okay I guess. To solve the clutter, I thought
about splitting up the class into several smaller ones, but that didn't
feel right, mainly because it would have gone along with an increase of
complexity (further interaction would be needed between several classes)
which just isn't worth it.

Now my other idea was to group functions which share certain semantics
(e.g. signal handlers) into separate compilation units. However, this
would mean breaking up the class and spreading it over several files. I
had a look at the Nautilus source code, and that's how they do it and I
think it's a really good approach, but it's written in C afterall, so
I'm not sure if that applies to C++ as well.

Is that bad practice in C++? What would you do instead?

I think it's a fair practice. If there were an option of making several
classes, I'd prefer that, but since there isn't (or so you claim), putting
a class in more than one translation unit is just fine. If neither were
an option, I'd probably put them in more than one file, and then created
a file with a bunch of #include for all those sources. Then you'd have
only one translation unit, although it sometimes creates unreasonable
stress for the compiler/optimizer. Recently I had to downgrade the 'O'
flag for a compiler that was unable to handle translation units each
about 130-140K.

Bottomline: do split them.

V
 
G

Greg

Matthias said:
Hello,

this more a question about good practice than it is about the C++
language itself, but still... my question is this:

I have a class representing the main window of my application which is
really growing big. Well, most of the action is happening in the main
window in my app so that's okay I guess. To solve the clutter, I thought
about splitting up the class into several smaller ones, but that didn't
feel right, mainly because it would have gone along with an increase of
complexity (further interaction would be needed between several classes)
which just isn't worth it.

Now my other idea was to group functions which share certain semantics
(e.g. signal handlers) into separate compilation units. However, this
would mean breaking up the class and spreading it over several files. I
had a look at the Nautilus source code, and that's how they do it and I
think it's a really good approach, but it's written in C afterall, so
I'm not sure if that applies to C++ as well.

Is that bad practice in C++? What would you do instead?

Regards,
Matthias Kaeppler

Splitting an implementation of a class between two files should not
cause any problems. Nor would I say that doing so per se is considered
bad practice, though it is somewhat unusual.

It's far more likely someone would question why the implementation of a
single class is so large to begin with. After all, the more code that
is piled into a class, the less of a "class" it becomes. Classes should
provide encapsulation, coherency, and focus to a program's code. Those
benefits seem unlikely to be attained from a class that needs more than
one source file just to contain it.

I would guess that a good portion of the code in the class could be
moved outside of it. Only code that needs to execute as a class method
should remain as part of the class. Doing so actually improves
encapsulation. There's an article on this very topic by Scott Meyers
that may be relevant. I found it online, although registration may be
required in order to read the entire article:

http://www.cuj.com/documents/s=8042/cuj0002meyers/

Greg
 
M

Matthias Kaeppler

Greg said:
It's far more likely someone would question why the implementation of a
single class is so large to begin with. After all, the more code that
is piled into a class, the less of a "class" it becomes.
You mean like Java does? Sorry, couldn't resist :D

No seriously, you're right of course. I also thought about this issue,
but I feel that these methods (which are for a good part signal
handlers, just tons of them) belong semantically to the class, that's
why I didn't want to split the class into smaller ones. I mean, I
/could/ introduce some sort of controller class, which would take care
of handling all the signals, but it would need to modify private members
of the MainWindow class, and thus would have to be friend'ed, thereby
breaking encapsulation even more (most signal handlers modify the
behavior of the window in some form, so most of them need to access
private data).
I would guess that a good portion of the code in the class could be
moved outside of it. Only code that needs to execute as a class method
should remain as part of the class. Doing so actually improves
encapsulation. There's an article on this very topic by Scott Meyers
that may be relevant. I found it online, although registration may be
required in order to read the entire article:

http://www.cuj.com/documents/s=8042/cuj0002meyers/

Hm, too bad you have to sign up to read it, sounds interesting. Well, I
could read enough however to understand where Meyers is going. Applying
this view to my problem, I don't think that all these signal handlers
should be made global functions (for some of the reasons mentioned in
the article snippet, such as the need for overriding base class methods).
I would also have to vastly expand the class' interface at the public
level, because the global signal handlers would have to modify the
window's state.

I don't think that's a serious option in my particular case, though it
was quite insightful to read about it. I think, along with Victor's
comment, I'll stick to my plan. Thank you both.

Regards,
Matthias
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top