The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Good or Bad: One Function Per File

I'm considering adopting a practice (for various reasons) of only allowing one function to be implemented in a given C++ file, similar to my existing practice of only implementing one class in a file.  My main reason for doing this has to do with a unit testing scheme I'm thinking of implementing.

Can anyone think of some drawbacks (or advantages) of this?  So far, the only drawback I can think of is that this would potentially involve a proliferation of files.

And I don't want to be a "proliferator".... :)
Meganonymous Rex Send private email
Tuesday, January 23, 2007
 
 
I guess with the right IDE or text editor it could all work without getting in the way too badly.  Seems pointless to me, though.

It seems like it takes the "developers are idiots, so we'll put them in a strait jacket" philosophy of Java one step further.
Richard P
Tuesday, January 23, 2007
 
 
You may have thousands of files in a directory. That doesn't sound like an accessible organization.
son of parnas
Tuesday, January 23, 2007
 
 
Bad. I've known someone who did this. You expect the file to be named the same as the function. So every function addition, renaming, or removal impacts the build project as well. It is a roadbloack to refactoring.
onanon
Tuesday, January 23, 2007
 
 
Some 'C' programmers followed this practice.  The drawback of it is you get THOUSANDS of files for a reasonably sized application.  And you tend to lose the 'belonging' relationship, unless you adopt suitable nameing rules.

Personally, I prefer the "class per file" approach -- one .h file for a specification, and one .C (or .C++, or .cpp) file per class.  And typically a 'globals.h' file to make customization easier.

Note many toolsets support this approach (like UMLStudio from Pragsoft) and will auto-generate class diagrams from this, AND will auto-generate code from an entered class diagram.

Even when I did 'C', I usually wanted a file to hold a related 'library' of calls -- the file preserved that "belongs to" or "related call" relationship.  Also let me re-use code by a simple #include of the .h and a tweak of the make file to link in the .c file.

So, on the whole, I think we've found "one function per file" is not a good thing.
AllanL5
Tuesday, January 23, 2007
 
 
I've seen people (years and years ago) who had picked up this particular religion.  I'm talking 'C' programming here.

I'd say that for projects of any size, it is something I would avoid.

Another variant I've run into, that actually had some value, was to group functions by file (which is basically some sort of functional/esthetic issue) and then order the functions in alphabetical order.  The attempt here was to improve the lookup time when you had paper-based code reviews.

Seeing as how IDEs hide a lot of nastiness, it probably doesn't matter all that much anymore.
old.fart Send private email
Tuesday, January 23, 2007
 
 
The benefits of this unit-testing scheme would have to be significant to outweigh the cost in terms of the complexity of your file structure.

Could you provide more information on this unit testing scheme?
Duncan Bayne Send private email
Tuesday, January 23, 2007
 
 
I'm not saying one C++ "class method" per file, I'm saying, one standard old "global function" per file.  In a reasonably modern C++ application, I don't expect there to be thousands of global functions, and therefore don't see why this would be a problem.

Does this change anyone's answer?
Meganonymous Rex Send private email
Tuesday, January 23, 2007
 
 
More specifically:

1) A given .CPP file would either contain the complete implementation for a class.

OR

2) A given .CPP file would contain the complete implementation for a single (global) function.

One person made a point about refactoring that is a strong negative against my idea: binding the name of the function to the filename like Java classes.  That seems like something that would waste time down the road.

I did want to point out, though, that I was not advocating or thinking about creating a file for each METHOD of a class.  That would be nuts.
Meganonymous Rex Send private email
Tuesday, January 23, 2007
 
 
Why have any global functions (except main, and anything you need to interoperate with C) when you could have public static methods instead?
Christopher Wells Send private email
Tuesday, January 23, 2007
 
 
Nope, I'd still go with the "library" code approach.  Depends on how many 'global' old-type c code you have, and how many different 'purposes' there are.

I once wrote a VMS compatibility layer of calls for my code, so I could test it on a PC under Visual Studio (one compatibility file) or on the VMS 'native' system (a different compatibility file).

I think I wound up with like 25 different routines, but a single VMS file and a single Studio file.
AllanL5
Tuesday, January 23, 2007
 
 
With large C projects I always found it better when they're grouped by logical module, like PortIO.c, NetworkFunctions.c, GUI.c etc.
Steve
Tuesday, January 23, 2007
 
 
The big disadvantage to "one function per file" is that limits the ability of the compiler to optimize and increases compile time.
Ben Allison Send private email
Tuesday, January 23, 2007
 
 
> Why have any global functions (except main, and anything
> you need to interoperate with C) when you could have
> public static methods instead?

As I said, there shouldn't be many.

But that doesn't mean I'm going to say that there's never a reason.  One example I can think of off the top of my head: in my bag of tricks I have my own version of the CreateThread() function that takes the same parameters as CreateThread()  but calls _beginthreadex instead. 

But you guys sold me against my previous idea, I'm going to go back to putting things like that in a utility.cpp file and forget about it.
Meganonymous Rex Send private email
Tuesday, January 23, 2007
 
 
I worked on a project that did the one function per module structure. It was a database engine for VMS written in C. I liked it in that environment.

Benefits:
- Makes dependencies more obvious.
- Takes less time to build if you have a sophisticated make system.
- Easy to find source code for a function if you have thousands of files (which is rare).
- For projects based on subsystems you can use the directory structure to enforce the project structure.
- It helps in isolating production problems for new point releases.
- Developers don't need all of the source. Just the objs and headers. The objs are typically merged into libraries.
- Helps in profiling performance for optimzation.

Problems:
- If your using an IDE its not a good fit. Slows down the project load.
- You need a good make system that integrates with your source control.
Phil C Send private email
Tuesday, January 23, 2007
 
 
Let me add $0.02:

+ If you have a library and link against it statically, only code for methods that are called will be linked, resulting in smaller executable.

- Compile time will increase as there's nontrivial overhead per file (parsing #included headers, etc.)
Jeff Zanooda Send private email
Tuesday, January 23, 2007
 
 
I would evaluate putting one function per file on a case by case basis, but I would not make it a practice.

If there is value, in selected cases, of having a single function in a file, then certainly do it.

As a standard practice, however, I try and group functions logically based on inputs and outputs.  I have often found stand alone global functions often morph into classes as time goes on.  It simplifies the effort of converting a group of functions into a class if they are already colocated.  I would suggest that there is probably a little bit finer grained decomposition than lumping them all into Utility.cpp; consider something a bit more descriptive like ThreadLibrary.cpp or LogLibrary.cpp.

If there is real benefit in isolating some functions into individual files, then do it.  I would treat this, however, as an exception rather than a rule.
Wayne M.
Wednesday, January 24, 2007
 
 
"+ If you have a library and link against it statically, only code for methods that are called will be linked, resulting in smaller executable."

Per executable, yes, but what if you have 20 of them?
UNIX Guy
Wednesday, January 24, 2007
 
 
UNIX Guy:

You're saying what if you have 20 executables that all link to a given static library?  (The classic argument for dynamic libraries.)
Meganonymous Rex Send private email
Wednesday, January 24, 2007
 
 
If you have 20 executables that use the same library you'd be probably better off making the library dynamic, one function per file or not. 

The example I had in mind was from embedded world, where size matters.  I noticed that executable size went through the roof when I used something trivial like strcpy().  It turned out that in the standard library I was using at the time strcpy() and sprintf() implementations happen to reside in the same .c file, hence corresponding .obj file was quite large.  The roof was at 16 KB :)
Jeff Zanooda Send private email
Wednesday, January 24, 2007
 
 
From memory, I think there is was a good reason why many 'C' programmers had only one function per file.

Namely, EARLY C compilers had a limitation in that each file had to have exactly one function per file. (Hmm, kinda like one class per file in Java?, though you can have nested classes so that's not a big deal).

I do not think that it's a good reason *today*, but if a project is already consistent with just having one function per file, why break that pattern?
Arafangion Send private email
Thursday, January 25, 2007
 
 
I  think one would have to go pretty far back in time to find a C compiler that only supported a single function per file.  I've worked with C since the 1980s including some K&R style C (no signatures and no prototypes).

Actually, the greater technical difficulty is to support multiple files.  The difficulty in Linkers is not identifying the calls into the file, but the calls out of the file.
Wayne M.
Thursday, January 25, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz