Aura: More Decoupled Than Symfony 2 and Zend Framework 2

The guys at PHPMagazin have posted a followup question about the Aura Project for PHP. Here is our original English conversation.


I'd like to follow up on the last point where we talked about other frameworks. I think that the second generations of symfony and Zend Framework have gone through a huge decoupling process. This becomes evident when you look at symfony2 components being used in Drupal 8 or web tutorials which show you mixed use of zend- and symfony components.

So I think we could elaborate further on that last bullet point we discussed. Does the above change your angle in this regard?

Not in this case. Being able to use Symfony2 components or ZF2 modules is not quite the distinction I am making. The distinction is that all Aura packages (with the exception of the Framework package) are completely independent, and have no cross-package dependencies, whereas at least some of the components from Symfony2 and ZF2 have dependency requirements.

By way of comparison, let's examine something that ought to be relatively straightforward: input validation and filtering. We'll start with ZF2, then move on to Symfony2, and end with Aura. In each case, we will try to download the package and run its tests; this should be a good indicator of whether or not the package can be used independently. We will discover that you can't do it at all with ZF2, you can kind of do it with Symfony2, and that it's trivially easy with Aura.

Zend Framework 2

Let's start by downloading the ZF2 InputFilter package. It doesn't appear to be available for download by itself -- there is the main ZF2 repository at Github https://github.com/zendframework/zf2 but that's the whole framework, not just the InputFilter.

OK then, we can at least use Composer to incorporate the InputFilter into a project. We will set up a Composer file per the ZF2 instructions and install the InputFilter package. Our composer.json file looks like this:

{
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.zendframework.com/"
        }
    ],
    "require" : {
        "zendframework/zend-inputfilter" : "2.0.*"
    }
}

After downloading Composer into the same directory, we run the installer, and this is what we see:

$ ./composer.phar install
Loading composer repositories with package information
Installing dependencies
  - Installing zendframework/zend-stdlib (2.0.5)
    Downloading: 100%

  - Installing zendframework/zend-servicemanager (2.0.5)
    Downloading: 100%

  - Installing zendframework/zend-filter (2.0.5)
    Downloading: 100%

  - Installing zendframework/zend-i18n (2.0.5)
    Downloading: 100%

  - Installing zendframework/zend-validator (2.0.5)
    Downloading: 100%

  - Installing zendframework/zend-inputfilter (2.0.5)
    Downloading: 100%

zendframework/zend-stdlib suggests installing pecl-weakref (Implementation of weak references for StdlibCallbackHandler)
zendframework/zend-servicemanager suggests installing zendframework/zend-di (ZendDi component)
zendframework/zend-filter suggests installing zendframework/zend-crypt (ZendCrypt component)
zendframework/zend-validator suggests installing zendframework/zend-db (ZendDb component)
zendframework/zend-validator suggests installing zendframework/zend-math (ZendMath component)
Writing lock file
Generating autoload files
$

In order to use input filtering from ZF2, six other packages are required, and a few others are suggested.

Now that we've installed it, where are the tests? They're not provided with the Composer package, although I suppose they are available with the framework as a whole. It appears the Zend offering is not entirely self-contained.

(If we look closely, we see that InputFilter is composed of at least two other packages that might suit our needs, zend-filter and zend-validator. However, when you examine them, they're not comparable to Aura.Filter and Symfony2 Validator.)

Symfony 2

Let's do the same thing with Symfony. This time it is downloadable through Github: https://github.com/symfony/Validator

Let's clone the package and run the tests.

$ git clone https://github.com/symfony/Validator.git
Cloning into Validator...
remote: Counting objects: 3459, done.
remote: Compressing objects: 100% (672/672), done.
remote: Total 3459 (delta 2708), reused 3451 (delta 2700)
Receiving objects: 100% (3459/3459), 621.73 KiB | 730 KiB/s, done.
Resolving deltas: 100% (2708/2708), done.
$ cd Validator/Tests/
$ phpunit
[phpunit fails]

It appears we can't just download the package and run the tests. The README states we need to use Composer and install all the --dev dependencies, so we'll do that. First we download Composer into the cloned repo, then:

$ ./composer.phar install --dev
Loading composer repositories with package information
Installing dependencies
Nothing to install or update
Loading composer repositories with package information
Installing dev dependencies
  - Installing symfony/yaml (dev-master bed4fdd)
    Cloning bed4fddc24392513e01b32a78d600b1272ed9a6c

  - Installing symfony/locale (dev-master 2dceded)
    Cloning 2dcededb060dfb6289ad8bb3f2a7a4e00929c4dc

  - Installing symfony/http-foundation (dev-master 067c310)
    Cloning 067c310fe4d0691a24adc97f39500233a58e42cb

Writing lock file
Generating autoload files

Interesting: in order for the tests to run we need three other packages. It looks to me like there are cross-package dependencies. Examining the codebase reveals this to be true:

  • If you want to use the YAML loader included with the Validator, you need that YAML package after all.

  • If you want to validate against anything related to locales or languages, you need the Locale package. For example, the LangaugeValidator.php file makes a static call to SymfonyComponentLocaleLocale::getLanguages().

  • If you want to use Annotations with the Validator, it looks like you need Doctrine, which isn't a part of the Symfony vendor hierarchy at all. Goodness knows what that will require.

Anyway, now we can run the tests; I have omitted the test progress output.

$ phpunit
PHPUnit 3.7.9 by Sebastian Bergmann.
...
Time: 8 seconds, Memory: 17.75Mb

OK, but incomplete or skipped tests!
Tests: 987, Assertions: 1091, Skipped: 12.
$

12 tests have to be skipped because of missing dependencies. When we run phpunit --verbose we discover that:

  • 3 tests are skipped are because APC is not loaded for the command line, which is not such a big deal;

  • 6 are skipped because "The Doctrine Common library is not available";

  • 3 are skipped because "Annotations is required for this test".

As with the ZF2 InputFilter component, it looks like the Symfony2 Validator component is not entirely self-contained. It has external dependencies that must be fulfilled in order for it to be fully useful.

Aura.Filter

Finally, we have the Aura.Filter package. It is downloadable through Github at https://github.com/auraphp/Aura.Filter. Let's try to clone it and run the tests; I have again omitted the test progress output.

$ git clone git@github.com:auraphp/Aura.Filter.git
Cloning into Aura.Filter...
remote: Counting objects: 1105, done.
remote: Compressing objects: 100% (373/373), done.
remote: Total 1105 (delta 631), reused 1076 (delta 602)
Receiving objects: 100% (1105/1105), 725.94 KiB | 606 KiB/s, done.
Resolving deltas: 100% (631/631), done.
$ cd Aura.Filter/tests/
$ phpunit
PHPUnit 3.7.9 by Sebastian Bergmann.

Configuration read from /Users/pmjones/Aura.Filter/tests/phpunit.xml
...
Time: 4 seconds, Memory: 9.75Mb

OK (1009 tests, 1443 assertions)
$

No external dependencies, and nothing extra is needed for the tests to run. The package is completely self-contained, independent, and decoupled. Now compare the memory use and time taken to that of Symfony2: about half the memory used, and about half the time taken, to complete about 30% more assertions in the tests. (Incidentally, we have 100% test coverage of the source classes, but I don't know how that compares to Symfony and Zend.)

Conclusion

None of the above is to meant to say that Zend Framework or Symfony2 are poorly architected, not useful, or any other negative thing. They are good projects, and the components appear to be good too.

The only thing I am saying is that their offerings of separate components are not always very well decoupled. This is because they started with a framework and tried to extract pieces from it. (To be fair, some components from both of those projects really are dependency-free, but not all of them.)

But in Aura, with its "libraries first" approach, every package is truly decoupled, independent, and self-contained, with zero cross-package dependencies. That is the major difference I want to emphasize.

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.