This is the mail archive of the
mailing list for the glibc project.
Re: guidelines for code reuse vs. one-function-per-file?
- From: Roland McGrath <roland at hack dot frob dot com>
- To: Torvald Riegel <triegel at redhat dot com>
- Cc: GLIBC Devel <libc-alpha at sourceware dot org>
- Date: Wed, 7 May 2014 14:13:26 -0700 (PDT)
- Subject: Re: guidelines for code reuse vs. one-function-per-file?
- Authentication-results: sourceware.org; auth=none
- References: <1399459406 dot 32485 dot 12676 dot camel at triegel dot csb>
It's always a judgment call.
There are a few reasons to prefer one function per file:
* Avoids linking in dead code for static linking.
* Eases navigating the source when the file name matches the function
you're looking for. (Of course there are a zillion other ways to
navigate the source.)
* General cleanliness of the source: it's easier to think about one thing
at a time, so less clutter when looking at a function is good.
* I vaguely feel like there are some other benefits I'm not thinking of. ;-)
These boil down to efficiency (easy dead code avoidance without
resorting to -ffunction-sections or whatnot) and maintainability
(everything else). So think about serving these principles well and
balancing them against each other, and you should come to the right
answer for each case.
All else being equal, do one function per file. If doing that harms
maintainability because of duplicated code or other reasons, give it
more thought. If you come to a contrary conclusion, then be sure to
write a comment in the file briefly explaining your rationale.
If two related functions are almost always used together (e.g. a lock
and an unlock) and it's better for maintenance to keep them in the same
file, then that's fine. If instead the second (or nth) function is
relatively tiny and it being dead adds very little dead code (e.g. two
entry points that use the same internal function for almost all the
code), then that's fine enough too.
In general, if there is code to be shared that should be accomplished by
sharing the code. Source code duplication is one of the greatest
menaces to maintainability, so take it very seriously. Don't hesitate
to break out a private subroutine and call it from two API functions.
When it's not a clear case from the preceding paragraph, then put the
shared code in a third, private file. If either you're pretty sure it's
important that it be inlined in both places, or it's small enough that
you're sure it won't do measurable harm to inline it (and thus bloat the
total code size), then put the subroutine in a private header file
included both places. If it's a larger subroutine or a cold-path one
where it's very doubtful that inlining is worthwhile, then put it in its
own separately-compiled file.
There's a tension in the other direction toward letting the compiler
decide when inlining is optimal and when not (especially when it often
might decide to inline, clone, and outline, so it's been "inlined" to
two call sites but the bulk of the subroutine is in the shared clone).
That leads toward putting multiple functions in one file so that the
compiler can arrange to make them share code. But I think we should
just not worry about this and instead tend strongly toward separate
files. I think the optimization issue would be addressed better by
someone working on using gcc's LTO to build our DSOs.