On Project Structure; or, The Framework/App Is Not Special

(I apologize for the hasty writing here; this subject makes me impatient.)

Reading this post from Code Rabbi makes me reflect on project structure and organization. Frankly, most project structures (as from CodeIgniter, Cake, and all the popular frameworks since then) strike me as misdirected. They’re examples of why the project maintainers think their code is somehow special and different, and that the application built from it is also somehow special and different.

Your framework and application code are not special. Their code does not go in a special place. There’s no need for a top-level “app” directory with its own special subdirectories. There’s no need for a special naming convention to keep your different application-specfic code in specific places.

We had PSR-0, and now have PSR-4, and the Composer autoloader, to handle all that for you. Just use namespaces. All you need for code at the top level of your project is a “src” directory, where all your app code goes, just like all your library code goes in a “src” directory in a library package.

Instead of /app/controllers and /app/models, you have /src/Controller and /src/Model, or however else you want to organize your namespaced code. Then there’s no need for a special autoloading system or for hard-coded paths just for your application-level code. Add one single line to Composer that points to the src directory and voila, everything inside it loads for you.

That’s it. Nothing special. Just like every other library in your system.

(Again, this was hastily written. Please ask for clarfication if you feel you need it.)

Are you stuck with a legacy PHP application? You should buy my book because it gives you a step-by-step guide to improving your codebase, all while keeping it running the whole time.

16 thoughts on “On Project Structure; or, The Framework/App Is Not Special

  1. To be fair, I think there is a benefit to separating code which you wrote from third-party code. Generally, it’s a good policy to say that external code is to be left alone. A top-level folder which separates first-party from third-party is not a bad idea.

    There is also a benefit to other programmers to have a standard-ish directory structure for a project.

    • Absolutely agreed! In a Composer regime, that 3rd-party directory is the “vendor” directory. In addition, I might go so far as to say that 1st-party elements *that are not supposed to be dependent on the framework* (e.g. the Domain Model) should be in a separate repo and brought in as a 3rd-party element, as a way of enforcing separation.

      • Right.

        Most of the framework’s have LTS releases that don’t last very long(~3 years) and your domain model could easily outlive its delivery mechanism.

  2. I agree. I recently just renamed the ZF1 modules directory to src and flattened (removed) the /controllers directory.

    Although, it would be more convenient for the name of that directory to be ‘app’ simply so that when trying to navigate it, it does not start within the middle of the project directory but at the top (IDE navigation here).

    Even though I prefer the package (aka src) structure, I’ve found it easier to work with by merging/flattening the main packages into one package, so that there is only one src directory (they are now in the same repo). I think it would be great if an IDE would allow you to create your own project directory map rather than reading its raw pyhsical structure; maybe that is already possible?

  3. While I wholeheartedly agree to your point, I believe that the benefit of supplying a default project structure from the framework’s point of view is to make adoption easier, since it hands the developer a pre-packaged application that works out of the box. A beginner Laravel user, for example, wouldn’t know the inner workings of the IlluminateFoundationApplication, so the default structure is definitely useful.

    • A default project structure can live in /src/Web/Action, /src/Domain, and /config as easily as anywhere else.

  4. To be fair, I think there’s a place for both approaches, and what is described here in the above article is merely one man’s opinion. I manage many websites and they all build on top of CodeIgniter + my company’s own enhanced framework that sits on top of it. I would go crazy if there wasn’t a clear separation between different types of components and files.

    I worked for a coupe of months on a Node.js + some other nonsense (yet very popular) frameworks, and I was pulling my hair out trying to figure out what was what. Everything was a “module”, regardless of whether it was controller code or view code or model code. Diving into such a site and trying to figure out what was responsible for what gave me a headache (literally!). Needless to say, I didn’t stay with that project. I have been far more productive working with my CodeIgniter-based projects, and have had tremendous success with that approach to file organization.

    So, again, I believe that to each his own. Some will find one approach more useful than other approaches. That’s what makes this industry so fun and challenging. Always new ideas.

    • It is important because when you do not have a clue what are you doing, every whatever suggestion may yield a sensible outcome and further improvements on your confused mental state, especially if you are some sort of a Symblowme 2 evangelist, or you just started to create a very popular “DDD projects”, in PHPLand of course.

      I can only agree that this is better than the previous.

  5. “Your framework and application code are not special. ” Amen! Moreover, so many frameworks seem to assume you are building The One Final App in a greenfield with only The One True Framework. Most real businesses with which I’m familiar (and with my long and checkered career, that’s quite a few) don’t work that way. There’s always legacy code, legacy systems, multiple apps using multiple technologies, etc. etc. Rigid, framework-centric structures drive me crazy.

  6. I don’t think that I have anything new to add, only that the underlying argument is simply:
    – Keep framework specific configuration and bootstrapping separate from your application code
    – Keep your application code as a set of classes which are namespaced in the PSR-0 convention.

    The post by Code Rabbi, makes a good point of separating the “classes” from the “configuration” and from the “configuration as code” (binding of routes, filters and events). I’ve always been irritated by by the mingling of all these types of files and this looks like a well thought-out way of rationalizing all the different parts that come together to make an app run.

  7. What matters to me is not what things are called but that by having a certain name I can quickly realise what it is I am looking at. When I join a project that has files called SomeThing.core.php and somethingelse.app.view.php I at least know what the file is about. And while that is far from the best setup it beats the living daylights out of a project with files called stuff.php, bob.php and foo.php or worse core/comment.php and core/comments.php (yes I have actually seen that). The more naming conventions do to help me understand what another developer was thinking the better.

Leave a Reply

Your email address will not be published. Required fields are marked *