Federico Cargnelutti / Wiki

Scalable and Flexible Directory Structure for Web Applications

From Federico Cargnelutti

Jump to: navigation, search

Contents

Introduction

Designing a modular and component-based directory structure for your Web applications can seem like an easy task. If your system is small, it may seem logical to go with the simplest design possible, but if there’s anything more time consuming and complex than developing a new directory structure design, it’s trying to redesign an existing system that wasn’t developed with growth in mind.

Consistency

To ensure that your development and build processes work effectively in a team environment, it’s essential to start with a correct directory structure that is consistent across all of your development servers. Frameworks, for example, provide a standard directory structure to organize the content in a logical way, consistent with the architecture choices: MVC pattern and project, application and module grouping.

The directory structure of the Zend Framework:

project/
  app/
    modules/
      module/
        controllers/
        models/
        views/
          layouts/
          scripts/
  cache/
  config/
    dev/
    prd/
    stg/
  lib/
    Zend/
  logs/
  public/
    index.php
  tests/

The directory structure of Symfony:

project/
  apps/
    application/
      modules/
        module/
            actions/
            config/
            lib/
            templates/
  cache/
  config/
  data/
  lib/
  log/
  plugins/
  test/
  web/
    css/
    images/
    js/
    uploads/

The directory structure of Ruby on Rails:

project/
  app/
    controller/
    helpers/
    models/
    views/
    layouts/
  components/
  config/
    environments/
  db/
  lib/
  log/
  public/
    css/
    images/
    js/
    uploads/
  script/
  test/
  vendor/

Scalability and Flexibility

A small system may very well start with a single project, but as the business requirements grow, you may find it useful to divide the system into multiple projects. If you’re creating your directory structure from scratch, you have the opportunity to maximize scalability and flexibility.

Using a directory as a container for all of the shared libraries enables greater reuse of components. If a project needs to reference a specific library create a symbolik link, for example:

libraries/
  ezComponents/
  Zend/
    1.5/
    1.5.1/
    1.5.2/
    1.6/
 
projectA/
  library/
    Zend/ -> /home/libraries/Zend/1.6
  public/
 
projectB/
  library/
    Zend/ -> /home/libraries/Zend/1.6
  public/

File references should be used only to reference outer-project libraries (such as the Zend Framework) that are not specific to a project. On of the advantages of doing it this way is that project references are sensitive to changes, this means that you can automatically switch from one version to another one without having to distribute files across multiple projects.

There are two main models to consider for creating projects:

  1. Single application
  2. Multi-application

Single Application

The single application model allows you to break up your projects to provide a greater level of isolation and control. Think about which applications you want to work on in isolation, and create separate projects accordingly.

project/
  application/
    controllers/
    models/
    views/
  library/
    Zend/ -> /home/libraries/Zend/1.6
  public/

Or in larger systems, a modular single application model:

project/
  application/
    modules/
      module/
        controllers/
        models/
        views/
  library/
    Zend/ -> /home/libraries/Zend/1.6
  public/

These are simpler to work with and offer a number of significant advantages over the multi-application model. For example, it allows you to work on smaller subsystems, and therefore reduces the complexity of the project and the number of dependencies.

Multi-application

In some cases, you may want to divide your project into multiple applications. For example, if you want to reduce the number of files required on each application. This allows you to work on separate applications within the inner-project boundary. A single project approach is simpler, so split a project up into multiple applications only if absolutely necessary.

project/
  apps/
    applicationA/
      modules/
    applicationB/
      modules/
  config/
  library/
  public/

One of the disadvantages of using this model is that you are limited in the way you can break up your projects. This is because of the application dependency relationships. As a result, if you want to move a particular application to a different server, you are forced to copy all the dependent files, such as configuration files, layouts, schemas and/or specific components and libraries. Unless you have very good reasons to use a multi-application model, you should avoid this and adopt a single application model.

Naming Conventions

Ruby on Rails did a great job establishing a standard directory structure, and since then everyone has tried to conform to this structure as much as possible. For that reasons, when naming your folders you should aim for a consistent set of names, this can greatly simplify project organization. While it is possible to rename folders later on in the development cycle, you should avoid this if possible. For example:

Bad:

project/
  controllers/
  etc/
  ezComponents/
  models/
  templates/
  var/
    log/
    tmp/
  www/
  Zend/

Good:

project/
  application/
    controllers/
    models/
    views/
  config/
  lib/
    ezComponents/
    Zend/
  log/
  public/
  tmp/

Versioning

It is always good to assign unique version numbers to unique states of a project. These numbers are generally assigned in increasing order and correspond to new developments in the project.

project/ -> /home/project_latest_release/0.3
 
project_latest_release/
  0.1/
  0.2/
  0.3/
    app/
      modules/
        module/
          controllers/
          models/
          views/
    lib/
    public/

One of the advantages of doing it this way is that when a new version of the project is released, you only need to change the reference to the version number, as opposed to modifying the Web server configuration file. This speeds up the deployment process and allows you to rollback to a previous state of the project very easily.

Proposed Structure

The directory structure I use for my projects has been influenced by many frameworks, specially Rails, which defines a standard project structure. I’ve then added to this some things I’ve seen in real-world projects.

libraries/
  Zend/
    1.5.2/
    1.6/
 
mysite/
  build/
  migrate/
  www/ -> /home/mysite_latest_release/0.2
 
mysite_latest_release/
  0.1/
  0.2/
    app/
      cache/
      config/
      modules/
        module/
          controllers/
          i18n/
          models/
          properties/
          views/
            layouts/
            scripts/
      tmp/
    lib/
      Core/
      Zend/ -> /home/libraries/Zend/1.6
    public/
      index.php
    tests/

Web server configuration file (never changes):

<VirtualHost *:80>
    DocumentRoot /home/mysite/www/public
    ServerName mysite.com
    ServerAlias www.mysite.com
</VirtualHost>

More information

Personal tools