Thursday 12 March 2009

Code: File structure matters

When working on your software project, how much thought do you give to the shape of your project's file structure?

Many people plug away within their IDE of choice (most commonly Visual Studio or Xcode, but perhaps Eclipse or somesuch). They accept the default file structure imposed on them by the tool. Depending on the size and nature of your project this may be sensible. It may not.

I've seen gargantuan projects managed like this with thousands of source files in one directory. If the IDE provides a mechanism for drawing logical hierarchies of files, but leaves the filesystem in a mess does it matter?

Yes, it does.

Good file structure makes working with your project easier:
  • Managing/viewing code changes in source control is sensible, especially when you're using tools outside the IDEs limited set.
  • Introducing a newcomer to your project and showing them the structure is easier.
  • Using other build system is easier, perhaps significant when porting the code to another platform.
  • Navigating around the project outside of an IDE is easier.
  • It's easier to see old files that are no longer relevant and that can be deleted.
  • Keeping a tidy house encourages code quality in many other areas.
At the most basic level, I try to maintain these principles for file naming:
  • The file name matches contents of the file. Essentially, there is only ever one class per file, and the file reflects that class name. E.g. ClassName.java, or ClassName.h and ClassName.cpp)
  • Directory structure matches namespace/package names. E.g. Foo::Bar::ClassName is in the file "Foo/Bar/ClassName.h"
  • Tests are kept in consistently named files beside the corresponding source files. I create a tests subdirectory with a test file of the same name as its testee. E.g. "Foo/Bar/ClassName.cpp"'s unit tests are kept in "Foo/Bar/tests/ClassName.cpp"
  • For libraries, I keep the public header files in a covariant source tree. Internal "private" header files are therefore clearly distinguished from public heeaders. E.g. "include/Foo/Bar/PublicClass.h" with implementation in "lib/Foo/Bar/PublicClass.cpp".
The naming and location of derived built files (e.g. object files or java bytecode) is another thing. These days I like to keep another covariant tree containing object files. The trees are separates by target platform name and build type (release/debug/etc).

What rules do you follow to name and structure your software project? Do you know how to configure your development environment to change the default locations of files? Do you think this matters at all?

No comments: