107

I am an individual developer working, largely, on web-projects (W/LAMP) and, at times, on C/C++ (non-GUI) projects of about average scale.

I often struggle with structuring my source-code tree. In fact, usually, I don't complete a project without dumping the entire tree and rearranging the pieces three-four times which really takes up a lot of effort and moreover the end result does seem like a compromise.

Sometimes, I end up with over classification of source - very long tree of folders and sub-folders. At other times, I simply end up concentrating all files in a particular folder based on the larger purpose they serve and thereby leading to 'chaotic' folders in the source.

I would want to ask:

  • Are there any principles/logic/best-practices that can help me better at structuring my source tree?
  • Are there any graphical/diagrammatic techniques (for eg.: DFD in case of dataflow) that can help me visualize my source tree beforehand based on the analysis of the project?
  • What strategy to adopt to structure multi-media files-tree associated with the project?

About the bounty: I appreciate existing answers with the members sharing their own practices, however, I'd like to encourage more general and instructive answers (or resources) and more responses from the members.

6
  • 10
    I don't have time for an essay right now, but "name things for what they are", "put things where they belong", "keep similar things close to each other", and finally, "don't worry about it, you hopefully have an IDE that will help you quickly navigate between pieces of code". Jun 8, 2011 at 13:54
  • @John, I am not so good with IDE(s), I generally pull out a Notepad++ or vi depending upon the OS. That makes things a bit more difficult. The rest of the points are helpful but again it boils down to making tricky decisions like are log (error logs etc.) functions more closer to application logic or DAL or cache management or view managers. Errors have almost equal likelihood of occurring across any of them.
    – check123
    Jun 8, 2011 at 14:10
  • 3
    Maybe once you get to the point of having this kind of question, it's time to let some tools do some of the work for you. And logging is clearly a cross-functional concern, used by all parts of the application (if you're using the kind of code that needs logging). Another little saying is, "put the code above the code that uses it", so the logging should be near the top, maybe in \utilities. Jun 8, 2011 at 14:13
  • @John: Much appreciated. May be I should start looking for an IDE. Eclipse seems promising.
    – check123
    Jun 9, 2011 at 10:19
  • 1
    @check123 "...rearranging the pieces three-four times..." Common practice: “The management question, therefore, is not whether to build a pilot system and throw it away. You will do that. The only question is whether to plan in advance to build a throwaway, or to promise to deliver the throwaway to customers.” ― Frederick P. Brooks Jr., The Mythical Man-Month: Essays on Software Engineering Apr 14, 2017 at 13:11

11 Answers 11

25

The source tree layout should reflect the architecture; as a corollary, a well-structured architecture can lead to a well-structured source tree layout. I suggest reading up on the POSA1 Layers pattern, attempting to fit your architecture into a layered structure, then naming each of the resulting layers, and using that as a basis for your source hierarchy. Taking a common three-tier architecture as a baseline:

  • presentation/webService (present a web-service interface to our business logic)
  • logic/* (business logic modules go in here)
  • storage/sql (back-end storage APIs here - this uses a SQL interface to store to a database)
  • util/* (utility code - usable by all other layers, but that does not refer outside util, goes here)

Note that the layers do not contain code directly, but rather are strictly used to organize modules.

Within a module, I use the following sort of layout:

  • <module> (path to module directly; defines modular interface)
  • <module>/impl/<implName> (a specific implementation of the modular interface)
  • <module>/doc (Documentation for using the module)
  • <module>/tb (unit-test code for the module)

where the <module> is located in the repository according to the layer to which it belongs.

3
  • 6
    +1: Source tree layout should reflect the architecture - an obvious thing I was overlooking.
    – check123
    Jun 9, 2011 at 10:18
  • How do you manage secure files - files which only authorized users can access post login?
    – check123
    Jun 9, 2011 at 10:23
  • @check123 I'm not sure I understand the question. I focused on the organization of source modules, rather than supporting files for the project, and source code is usually intended to be accessible by everyone. (There are exceptions, and I use a dist/ directory above all code with non-standard use/modification restrictions.) Jun 11, 2011 at 13:33
62

I can't really give you much advice related to webprojects, but here's how I structure my tree in a programming project (mainly from a C/C++ perspective):

  • /
    • src — Source files written by myself
    • ext — Contains third-party libraries
      • libname-1.2.8
        • include — Headers
        • lib — Compiled lib files
        • Donwload.txt — Contains link to download the version used
    • ide — I store project files in here
      • vc10 — I arrange project files depending on the IDE
    • bin — Compiled exe goes here
    • build — The compiler's build files
    • doc — Documentation of any kind
    • README
    • INSTALL
    • COPYING

A few notes:

  1. If I'm writing a library (and I'm using C/C++) I'm going to organize my source files first in two folders called "include" and "src" and then by module. If it's an application, then I'm going to organize them just by module (headers and sources will go in the same folder).

  2. Files and directories that I listed above in italics I won't add to the code repository.

5
  • What's the difference between ide and build? Jun 8, 2011 at 16:44
  • 3
    ide is just where I store the project files themselves. build contains the object files generated by the compiler. Different IDEs may use the same compiler, so that's why I keep the the IDE project files separated from the object files built by the compiler.
    – Paul
    Jun 8, 2011 at 17:48
  • so build == obj (the term used by many other systems)
    – gbjbaanb
    Aug 10, 2011 at 15:53
  • @gbjbaanb Yeah, I guess. It doesn't really matter since that directory doesn't get pushed to the repository. :) I called it 'build' because that's what the IDE I was using att called it (Visual Studio).
    – Paul
    Aug 10, 2011 at 17:33
  • What if your exe need some dll to run? Do you copy all the dll files to the same dir as exe?Do you use some post-build events? Sep 13, 2016 at 9:24
18
+100

The Maven Standard Directory Layout is kind of specific to Java, but it may serve as a good basis for other types of projects as well.

Here is the basic structure (you could replace the java directories with php,cpp, etc):

src/main/java       Application/Library sources 
src/main/resources  Application/Library resources  
src/main/filters    Resource filter files 
src/main/assembly   Assembly descriptors 
src/main/config     Configuration files 
src/main/webapp     Web application sources 
src/test/java       Test sources 
src/test/resources  Test resources 
src/test/filters    Test resource filter files 
src/site            Site 
LICENSE.txt         Project's license 
NOTICE.txt          Notices and attributions required by libraries
README.txt          Project's readme

The structure basically breaks down to src/main and src/test then grouped by type.

9

Ideally, the organisation has a single repository, the structure of which is intended to increase engagement between engineering & business and promote reuse.

...\products\
...\products\productName\
...\products\productName\doc\

...\systems\
...\systems\systemName\
...\systems\systemName\doc\
...\systems\systemName\res\
...\systems\systemName\build\
...\systems\systemName\test\

...\library\
...\library\libraryName\
...\library\libraryName\doc\
...\library\libraryName\build\
...\library\libraryName\test\

...\devops\

products

One folder per product; helps communicate how the software supports the business.

Ideally, each "product" is little more than a configuration file indicating which systems to invoke and how they are to be configured. The doc subfolder could contain the top-level brief\spec & any promotional materiel etc...

By separating products and systems we communicate the potential of reuse to the customer-facing side of the business, and break down per-product silos. (This contrasts with the "product line" approach to the same problem)

systems

One folder per system; helps communicate the primary capabilities & opportunity/value of the contents of the repository.

  1. "Configuration management" files specifying build & deployment environments.
  2. System-level testing configuration (could be significant quantity).
  3. Top level logic & functionality; most heavy lifting being done by library functions.

library

Reusable components invoked by various systems. Most development activities are organised around the production of libraries, rather than systems, so reuse is "baked in" to the development process.

devops

Build, Continuous Integration & other Development Automation functionality.

Conclusion

The source tree is a key piece of documentation, and shapes the approach, structure and psychology of the business' relationship with its proprietary technology.

The drivers for this approach are explained in a bit more depth in my answer to this question: https://softwareengineering.stackexchange.com/questions/43733/who-organizes-your-matlab-code/59637#59637

1
  • Note: It may be useful to name folders in a way that is compatible with the sort of product hierarchies discussed in the INCOSE systems engineering handbook. Feb 10, 2018 at 21:07
5

I dont really know about conventions but all of my main projects are done using Symfony Framework and i have get used to a tree structure like follows:

root/

  • apps
  • app_name
    • config (app specific config files)
    • lib (app specific php files)
    • modules ( modular distribution of functionality)
      • module_name
        • templates (html)
        • actions (php code)
  • confing (project config files)
  • lib (php code that could be use in hole project)
  • model (classes that represent the project information)
    • base
  • form (php files that handle forms, this could be quite difficult to achieve without symfony)
    • base (base form classes)
  • web
  • css
    • images
    • file.css
  • js
  • log (log files that might be generated)
  • data (data specific information, like sql patches, or whatever)
  • sql
  • plugins (libraries used that could be merged with any app of the project)

If you are interested, please read the symfony documentation on the matter for further inquired (MVC and Code Organization on Symfony).

2
  • Is your CSS folder centralised? I means all your CSS (across the project) are in the same directory?
    – check123
    Jun 9, 2011 at 10:21
  • Not necessarily, you could divide it, but as most of my projects tend to have only 2 apps (frontend and backend), there are not that much css files (plugins always have their own web folder for abstraction)
    – guiman
    Jun 9, 2011 at 10:40
3

What I'm trying to do for each project is similar as :

  • src - source files, a folder for each namespace/package to easily retrieve files (even header files for C/C++)
  • ext - for externals/third-party libraries, it is simple to add externals (such as SVN repositories). Inside, a folder for each libraries (binaries and include files)
  • bin - for built binaries, could be quickly exported for release
    • inc - for C/C++ headers file (copied by IDE/makefile/etc...)
  • out - for all temporarily generated files (.class, .obj etc...) and it could be ignored (for example by SVN)
  • doc - for any documentation, usually generated with Doxygen
  • res - by placing resources here, it's possible to separate text source files and binary resources used by the program. I don't really have specific hierarchy inside.
    • config - for some configuration files
    • drawable - for some pictures or icons

All IDE's files or makefiles are saved directly at the root if you only use one of them.

3

My recommendation is to download a variety of frameworks or engines and see how huge development teams handled their folders layout.

There are so many ways to organize files that it's better to choose one, and try to stick to it at any given project. Stick to a particular convention until completion or revamping to avoid bugs and loosing unnecesary time.

You can download Laravel, Symphony or Codeigniter frameworks for web projects to have an instant folder layout that works.

So I will try to convey a folders layout common to any development:

MVC (Model View Controller) gives a good paradigm of organization.

Root source code could be src (C++) or app (web development)

A file structure that does not have a clear objective for the classes that it groups definitely will cause confusion. It's not only to organize code, instead it can sustain auto-loaders, class factory, wrap local storage, remote storage and namespacing.

This folder structure is derived and simplified from Laravel Framework. My preference on this post is plural naming but I use singular words in my projects.


src/storage (models/file-storage/api/mysql/sql-lite/memcached/redis implementations)

src/repositories (A wrapper of 'storage implementations' with some storage logic, a common interface and return result convention.)

src/services | logic | entities (App bussiness logic)

src/controllers (Used on web development to route server requests to your services)

src/modules | systems (Modular systems that extend your framework general functionality. Services can use modules but not viceversa)

src/helpers (Helper or wrapper classes like eg. string manipulation. Many times this could be on libs|vendor when third party)

src/types (Named enums)

public | build | output (web or c++)

config (Setup files. YAML is becoming popular for cross-platform config files)

cache

logs

lang (en/es/ru/...)

bootstrap (Starts the framework and app)

docs (Documentation written in markdown format .md)

tests (Unit testing)

database/migrations (Create database structure from scratch)

database/seeds (Fills your database with dummy data to test)

libs | vendor (all third party software. 'libs' on C++ and 'vendor' usually on php)

assets | resources (images/sounds/scripts/json/any media)

2

I do something like this. Works well for a cross platform game I'm doing in my spare time. Unfortunately in work, things are much less organized...

Output                      <-- Build outputs
Docs
External
   <libname>
      Include
      Lib
Data
<ProjectName>.xcodeproj
<ProjectName>VS2010
Source
Temp                        <-- Intermediate stuff from builds and other tools
Tools
2

For my teams, we try to enforce a standard structure across projects to make is easy to find things as the team switches context and to avoid having to relearn each time through. Not all projects need all systems so we start with the minimal set.

/Source/Component/Language

/Source/Component/3rd Party/

/Documentation/Requirements

/Documentation/Design

/Tests/Automated/Unit

/Tests/Automated/ToolName

/Tests/Manual

This results in some duplication, particularily under the 3rd Party code and libraries, but at least we never forget the answer to something like "What uses the RogueWave Editor?"

1
  • 2
    Capitalized path components look really silly and pointless to me. Why lot all-lowercase? That's so much easier to type for humans (while tools don't care, including WIMP file managers), and reads equally well thanks to path separators. A definitive win to me.
    – ulidtko
    Jan 16, 2015 at 16:11
2

I like the ideas presented in this page www.javapractices.com/topic/TopicAction.do?Id=205. Basically, the recommendation is to organize your project into features(or modules, components). In addition to the reasons presented there:

  1. Less cognitive load when you think about the scope of the code you are working on since you have a guarantee that any code in the feature your are working on is "feature-private".
  2. There is an added sense of security when you are guaranteed that you are only modifying code for given a feature. E.g., you won't break anything other than the feature you are working on. Again this is because of the "feature-private".
  3. Less cognitive load simple because there is less files you can see for a given package. I am sure everyone has seen a package that contain more than 15 files.

Note this is focused on Java packages (aka namespaces). For big projects, I do recommend, for the same reasons, dividing the project into multiple projects (as in multiple maven projects) that represents a business feature. For maven projects, I recommend this reading.

So far, the projects I was/am involved in does not follow these. There are many reasons, but here's a few:

  1. The misunderstanding of Java default access modifier (most misunderstood access modifier as per this book)
  2. "Argumentum ad populum": Prevailing culture of package-by-layer (probably caused by Reason #1)

I think there is a missed opportunity to prevent complexity if project source organization is not taken seriously at the start of the project as the architect Alexander said:

"As any designer will tell you, it is the first steps in a design process which count for most. The first few strokes, which create the form, carry within them the destiny of the rest." - Christopher Alexander

Depending on the size & complexity of a project, the missed opportunity to cut costs or ROI can be really big. (I'm interested to see a study to see the exact numbers for this)

1

With object orientated languages, you have the ability to build namespaces. That logical breakdown used to separate parts of the application to avoid coupling is the primary source of logical file location breakdown. Using coupling as a reason for breaking apart namespaces is a good place to start http://en.wikipedia.org/wiki/Software_package_metrics.

Others have spoken about setting up the project in relation to build, but once you get into the source itself, it's about what makes sense - just use how you logically break apart the code anyways.

Not the answer you're looking for? Browse other questions tagged or ask your own question.