34

I've been writing my own general-purpose PHP library for a while and I'm thinking about how to organize the directory structure, but I wanted to get people's ideas before I formalized the directory structure for the library.

Here is what I have so far: https://github.com/homer6/altumo/tree/master/source/php

I was thinking I could either do it "By Topic" or "By Category". So far, I can only think of one example that I like of the "By Category": Boost http://www.boost.org/doc/libs/1_46_1/?view=categorized

Also, Qt is organized by module, but I think it's a bit messy because everything is kinda stuffed into QtCore http://qt-project.org/doc/qt-5/qtmodules.html

Any ideas?

Thanks in advance.

UPDATE: I found a really great book that has shown me a number of great library design conventions to follow: http://www.apibook.com/blog/

UPDATE: I found an interesting article that mentions organization of code (http://highscalability.com/blog/2012/3/26/7-years-of-youtube-scalability-lessons-in-30-minutes.html). At the bottom, it says: "What is your code tree going to look like? He wants these words to describe it: simple, pragmatic, elegant, orthogonal, composable. This is an ideal, reality is a bit different."

mavroprovato
  • 7,085
  • 3
  • 34
  • 51
Homer6
  • 13,933
  • 10
  • 53
  • 77
  • I think you mean "directory structure" rather than "file system". ext3 is a file system. – Frank Farmer May 13 '11 at 21:26
  • Thank you, that's clearer. Updated. – Homer6 May 13 '11 at 21:33
  • Excellent question, and great answers so far. I'll just add that since chances are your class naming will correspond to the directory structure, this is an added motive to having directories/subdirectories make sense: `$req = new YourLib_HTTP_Request();` – Fanis Hatzidakis May 21 '11 at 18:26
  • I've answered that on another question asking the same already: Directory layouts are completely uninteresting. Make sure your autoloader can find the files. That's all there is to it. – Gordon May 22 '11 at 20:48
  • I'd take a look at Zend and its naming convention and layout. I think its one of the best organized PHP frameworks / libs. – mr-sk May 24 '11 at 02:29
  • don't forget the DRY principle (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself) – celsowm Dec 07 '11 at 18:13

7 Answers7

18

First of all, the chosen structure is a compromise decision, that means that you'll have to deal and prioritize some aspects over others depending on your purpose. There are some grouping criterias you could follow, such as:

  • Functional Cohesion, I think that should be the strongest one in your design. Classes/files/resources with the same or similar functionality should be together
  • Component Hierarchy, Depending on the granularity level you choose, that means if you prefer fine-grained components vs coarse-grained, you would have more or less files/resources in one folder. This can be controlled using folder hierarchy and nesting.
  • Change, Some files are more likely to be changed than others, you have to keep this in mind in order to provide a folder hierarchy depending on the probability to be modified.
  • Extensibility, For a framework to be useful and adaptable to almost any scenario you have to provide the possibility to extend components and functions. Adding a folder for extensions (aka plugins) is a good idea.

There are lot of criterias you should use, but always keep in mind the KISS Principle. You can search for package management in books like The Unified Software Development Process (Ivar Jacobson et al.), I hope this could be helpful.

Brad Larson
  • 168,330
  • 45
  • 388
  • 563
Joaquín L. Robles
  • 5,552
  • 8
  • 57
  • 86
  • Thanks for your comments Joaquín. +1 for adding some really good general ideas. I'm very keen on trying to make this design as simple as possible (modeled after Richard Feynman's attitude). You've given me some great areas to focus on and I'll definitely check out the book. Thank you. – Homer6 May 18 '11 at 18:07
  • You're welcome Homer6, another thing I forgot to mention, related to Extensibility is that is useful to define formally the services that a package provides (they're called service packages), because you'll realice if you grouped all the content well. Providing interfaces like that will make your desing more flexible and extensible (a component could be replaced with another that implements the same interface without any trouble). Maybe Jacobson's book is too theorical, but the explanations are pretty good.. – Joaquín L. Robles May 19 '11 at 01:18
  • 1
    This may be a departure from the topic, but what do you think of this? http://www.aspiringcraftsman.com/2008/12/28/examining-dependency-inversion/ Do you think any of these idea could be reflected in the design of the directory structure? – Homer6 May 19 '11 at 17:52
  • Excellent article Homer, I believe that this kind of service definitions depending on interfaces must be reflected in the directory structure, it will make the framework simpler to understand and easier to extend. For a general-purpose framework this should be a must, however this approach is capable to add extra complexity to the code, beware of this and you're done! :) – Joaquín L. Robles May 19 '11 at 18:08
7

Since it is multi-purpose library devoted to solve versatile problems or provide interfaces for common features, it is better to have structure by subject which may be DataType/Technology/Language/Protocol etc. like so:

+ Http
  - request
  - response
  + util
    - status_codes
+ Html
  - Validator
  + Form
    - UploadFile
  + Tag
+ JavaScript
  - JSON
+ Ajax
+ XML
  - Reader
  - Writer
  - Parser
+ DataType
  - Array
  - Integer
  - String
  - Double
  - Float
  + util
    - datatypes_cast_lib

On top we have:

  • Http which is a protocol so your Http.request would be an interface to perform Http request
  • Html which is markup language, so Html.Form.UploadFile will provide developer with features to create upload file forms
  • JavaScript which is programming language, so your Javascript.JSON would solve problems of conversions from JSON to Arrays maybe
  • Ajax which is technology
  • XML which is markup language
  • DataType which is ... well, data type.

Notice, that status_codes remain under util in Http. Every sub-library can have its own util features like DataType lib may need datatype_cast_lib to know how to juggle with datatypes.

This way of library organization mostly resembles organzation of PECL

Good question, BTW! I asked the same question myself frequently. I've been organizing and reorganizing my directories structure for years. It really depends on project. I've adapted structure above corresponding to structure you've provided here.

Nemoden
  • 8,038
  • 5
  • 35
  • 63
  • Thanks for your answer Nemoden. I forgot about PECL, but this is a really good (and tested) structure for web development. And while I think "By Subject" is covered with Joaquin's "Functional Cohesion", you gave a good example. +1 for your being clear and backing up your point. Thanks! – Homer6 May 19 '11 at 17:58
  • On my behalf, thank you for a good question: took some time to think out ;) – Nemoden May 30 '11 at 15:10
5

I'd suggest that you look at how things are organized in two recent php 5.3 frameworks, Symfony2 and Lithium.

The core devs behind them were active (along with other major framework developers and php celebrities) in defining standard php 5.3 naming conventions so that their respective components could play with each other, Zend, and other libraries/frameworks that might follow the same conventions:

http://groups.google.com/group/php-standards/web/php-coding-standard

In both cases, bundles/libraries are first-class citizens, and the two follow similar patterns when it comes to organizing them.

The Lithium core, in particular, is a library in its own right. It's organized like so:

$ ls
LICENSE.txt analysis    core        g11n        security    template    tests
action      console     data        net         storage     test        util

(I tend to find Symfony 2 a bit messier/less predictive, but that's just my own opinion.)

Denis de Bernardy
  • 67,991
  • 12
  • 114
  • 140
  • 1
    Thanks Denis. I've been following Symfony2 for a while. I think I agree with your opinion. I'll read up on Lithium though, I hadn't heard of it. Thanks. – Homer6 May 19 '11 at 18:20
  • Lithium was started by a few CakePHP core devs who wanted to move on with PHP 5.3. – Denis de Bernardy May 19 '11 at 23:11
4

Please be PSR-0 compatible, whatever structure you're going to use.

I personally suggest using the PEAR2 directory structure .

cweiske
  • 27,869
  • 13
  • 115
  • 180
3

I would say a good place to start is to look at how other frameworks and/or libraries are doing it.

Personally I like the way the Zend Framework is organized, with a fairly flat namespace, having all major components in the Zend directory. When using the Zend MVC project structure, you get an added autoloader translating _ to / all classes are named like Zend_Form and put in a file called Form.php inside the Zend directory, so that when calling new Zend_Form - the autoloader looks for Zend/Form.php. Only the 'main' class is directly inside the Zend folder, any additional class files, like exceptions and abstract are put inside a Zend/Form folder, and classnames named like Zend_Form_Exception - which cause the autoloader to look for Zend/Form/Exception.php.

Another point, is to keep backend logic away from any public_html folder. E.G - only files that should be directly accessible for users should be in here (javascript, css, and your loader.php + .htaccess). Then have loader.php include the files it needs, typically one directory level up.

External libraries are usually treated as such, and separated from the rest of the code in a /lib, /library and/or /vendor folder to indicate that external authors are responsible for these classes.

Jon Skarpeteig
  • 4,053
  • 6
  • 32
  • 52
  • Thanks for your comments Jon. To be clear, Altumo is not a framework, it's a library. I currently use symfony for my framework, which handles all of the things that you mention. Also, Altumo already has a class loader (based on namespaces), which was borrowed from symfony2. I'd like to keep Altumo as a library with as few dependencies as possible, and, if possible, I'd like the directory structure to indicate dependencies. However, I'm not too convinced that it's possible to indicate dependencies by the directory structure. – Homer6 May 18 '11 at 18:02
  • Zend Framework is more a library than a framework with only loosely coupled components. The dependencies of E.G Form is under the Form directory, while Form.php is in the root of Zend. All these base libraries are self-sustained and can be used outside of any framework, as they are independant of each others – Jon Skarpeteig May 18 '11 at 18:26
  • +1. Zend is organized excellently IMO. – mr-sk May 24 '11 at 02:29
3

I would say that it depends on how/if you use namepaces etc. Otherwise I would see a use for something like the ZendFramework directory layout (even though it's ugly as sin... hehe). Then I usually have a Corethat contains base functionality that all other parts might make use of like Array and String manipulation, Encryption/Decryption

+ Core
 - Array
 - String
 + Encryption
   - MD5
   - SHA1
   ...

Then I try to think of all subsequent folder as isolated parts/modules. Do I have a Jquery folder with a lot of JQuery helpers? Then that might be a good folder to add.

+ Core
 - Array
 - String
 + Encryption
   - MD5
   - SHA1
   ...
+JQuery

Does my JQuery require some HTML specifics that other "modules" might also use? Then that should go into Core. For instance my JQuery helpers might make use of JSON.

+ Core
 - Array
 - String
 + Encryption
   - MD5
   - SHA1
   ...
 + Encoding
   - JSON
+JQuery

If it's JQUery specific it should recide under JQuery.

+ Core
 - Array
 - String
 + Encryption
   - MD5
   - SHA1
   ...
+ JQuery
  - Datepicker

By always asking the question "Is this something that oter parts of my library will make use of and/or extend?" you will get a good idea if the functionality in question should be part of your Core or part of your specific library module.

inquam
  • 11,960
  • 14
  • 53
  • 95
  • Thanks for your contribution inquam. +1 for promoting a Core library and providing usage on how or when to use it. Thank! – Homer6 May 24 '11 at 14:50
2
<project name>/
    application/
        configs/
            application.ini
        controllers/
            helpers/
        forms/
        layouts/
            filters/
            helpers/
            scripts/
        models/
        modules/
        services/
        views/
            filters/
            helpers/
            scripts/
        Bootstrap.php
    data/
        cache/
        indexes/
        locales/
        logs/
        sessions/
        uploads/
    docs/
    library/
    public/
        css/
        images/
        js/
        .htaccess
        index.php
    scripts/
        jobs/
        build/
    temp/
    tests/

source: http://framework.zend.com/manual/en/project-structure.project.html

dynamic
  • 44,025
  • 53
  • 143
  • 223
  • Thanks for your answers yes123. As mentioned in comments to others, this is a common directory structure for a framework, not a library. Altumo should be able to be used in any framework (or even none at all). But please, give it another try if you have more ideas. Thx – Homer6 May 18 '11 at 18:10