What Application Layer Does A DI Container Belong In?

James fuller asks:

any thoughts about which layer of the application we should be using a DI container like Aura.Di? Highest layer possible?

Twitter is too constrained and ephemeral for a good response, so I’ll answer that question here.

First, we need to remember that a Dependency Injection container and a Service Locator are indistinguishable from an implementation perspective. (This is a view I accepted only recently.) The difference is in their use: if a container is ever placed into an object so the object can retrieve its own dependencies, that container is being used as a Service Locator. Conversely, if the container stays entirely outside an object so that dependencies are pushed into the object, the container is being used for dependency injection.

If we accept that description, the proper layer for a DI container is outside every other layer in the application (with the possible exception of Factory classes). That means the DI container is part of the bootstrapping code that sets up the application, and not part of anything else.

As an example, we can imagine a web application bootstrap script that looks like this:

<?php
// set up the autoloader
include '/path/to/autoload.php';

// create and set up a Container
$container = new Container;
$container->load('/path/to/container_config.php');

// retrieve a front controller service and run it
$front_controller = $container->get('front_controller');
$front_controller->exec();
?>

The purpose of the bootstrap is to create and configure the container with all its services and settings, then pull one object out of the container and invoke it. None of the objects in the system has to know that the container even exists. All of the objects are being created via the container, so in a way the container “contains” the entire object graph.

The part I had the hardest time getting about real dependency injection was this: If you have a class 2 or 3 layers down in the application, and that class needs dependencies, how do they get injected? Don’t you have to pass the dependencies through the intervening layers, and then doesn’t that break a lot of rules, along with violating plain common sense? And what if that class needs access to several different but related objects, but doesn’t necessarily know what they are in advance?

The key for me was realizing that all object creation work happens in the container and not in the classes themselves. This is an alien way of looking at things for most PHP developers, who are more used to Singleton, Registry, and Service Locator, not to mention static calls to ActiveRecord objects. All of these patterns of usage mess with separation of dependencies, but are very common in PHP land, and form the basis of most PHP developers’ understanding of how to work with dependencies.

It took me a year to really “get” the concept of dependency injection, under tutelage from guys like Jeff Moore and Marcus Baker, along with the writings of Misko Hevery. Once I understood it, I wrote the Aura.Di readme file as an introductory document to step readers through the various stages of dependency allocation. Perhaps that document will be helpful to others, even if they don’t choose Aura.Di as a container.

Afterword

If you work with a legacy application, you already know how hard it is to track dependencies throughout the code. Sometimes the dependencies are global, sometimes they are created inside that class that needs them, and sometimes there is a service locator implementation floating around inside the classes. This makes it frustrating to track down bugs and make wide-ranging changes, and terribly difficult to write tests because everything depends on everything else.

But it doesn’t have to stay that way. My new book, Modernizing Legacy Applications in PHP, gives detailed instructions that will lead you step-by-step from an include-oriented mess of page scripts to a modern architecture using dependency injection techniques.

You can buy the book in early-access mode today, or sign up on the mailing list below to get more information as it becomes available!

Sign up for Modernizing Legacy Applications in PHP:

First Name Email

“Page Script” As A Degenerate Controller

I read a good conversation on Reddit last week titled Thoughts on MVC vs. Pages for Everything?. Short version: the OP asks about the advantges of using a formalized model-view-controller system vs a series of typical PHP page scripts. The entire discussion is worth reading.

As the author of a book on modernizing legacy applications in PHP, this is a topic I am very familiar with. Almost all of the legacy applications I’ve had to deal with were page-based. In doing the work to modernize them, there comes a time where the page script has been refactored to look very much like a page controller, with some distinct but not critical differences. As such, I have come to consider the typical PHP page script to be a degenerate form of a page controller. With a little imagination, I think it’s easy to see why.

First, recall the basic operational cycle of almost every PHP framework ever, including the micro-frameworks:

  • a bootstrap index.php file that does some setup work, which hands off to …

  • a front-controller (typically a router/dispatch system) which picks …

  • a page controller or action method that calls services and collates the results into a data structure, which is passed to …

  • a view layer that renders the results for the client.

(In an earlier version of this dispatch cycle I split “page controller” and “action method” into two separate steps, and in many cases they may still be two separate steps.)

When we look at this cycle, it’s not so hard to envision a plain PHP script doing the same things. The web server itself becomes a simplified front controller+router+dispatcher, picking the “controller” (page script) to run based on the URL path mapped to the file system. After that the work is exactly the same, albeit combined into a single blob of code.

Even then, the page script can keep itself in good order by using service objects instead of embedding all the logic in one place. It should be easy to imagine converting a page script that combines the setup, data retrieval, data manipulation, and data output concerns as a blob of intermingled code, into something more like the following, where the concerns are in blocks:

<?php
// config, global vars, autoloader, etc
require_once '../setup.php';

// dependencies
$request = new Request($GLOBALS);
$response = new Response($GLOBALS);
$db = new Database($user, $pass, $host);
$service = new Service($db);
$view = new View;

// data retrieval
$page_number = (int) $request->get('page', 1);
$records = $service->fetchPage($page_number);

// data rendering
$view->setTemplate('/path/to/template.php');
$view->assign('records', $records);
$content = $view->render();

// send back to client
$response->setContent($content);
$response->send();
?>

That page script is not wildly different from what goes on inside a formal MVC framework. Yes, there are still some legacy elements. These include the global require setup at the top, the use of query parameters instead of path-info parameters, and the lack of a formal DI container (although for scripts like this a container proper might be overkill at the start).

On the other hand, most of the work is being done in classes and objects, not embeddded directly in the page script itself, just as you would see in a formal controller class method. These support classes and objects are independently testable; only the page script “controller” itself is not. But be honest here: of all the formal controller methods you have seen in the wild, how many were independently testable? My guess is “not many.”

Once we have refactored a page script to something like the above form, it becomes a lot easier to see how we might convert this degenerate controller over to a formal MVC framework with even further separation of concerns.

Afterword

Are you overwhelmed by a legacy application full of page scripts, spaghetti includes, and global variables? Do you want to improve the quality of the code, but don’t know where to begin or how to proceeed?

My new book, Modernizing Legacy Applications in PHP, gives step-by-step instructions on how to get your code under control and keep your application running the whole time.

Buy the early access version now and get free updates as it is completed, or sign up on the mailing list below for more information and a free sample chapter.

Sign up for Modernizing Legacy Applications in PHP:

First Name Email

Composer: Undefined Method Related To Global Install

I just updated the Aura v2 libraries to use PSR-4 via Composer instead of their custom autoload.php files, but when I started my integration tests for the Aura.Project_Kernel, I got this error:

PHP Fatal error:  Call to undefined method Composer\Autoload\ClassLoader::setPsr4() in /Users/pmjones/Code/auraphp/develop-2-projects/Aura.Project_Kernel/cli-project/vendor/composer/autoload_real.php on line 38

Even after a composer self-update the problem remained.

It turns out the problem was related to having issued composer global require phpunit/phpunit=3.7.*. The various Composer global vendor files were overriding the local ones in the project. I discovered this only by calling var_dump(get_included_files()) in the project-specific autoload_real.php file.

I ended up deleting ~/.composer (the global Composer location) and re-installing PHPUnit, but looking back on it, perhaps a composer global update would have solved the problem as well.

UPDATE: Christophe Coevet in the comments indicates composer global dump-autoload would have done the trick as well.

Honest Estimates

From Cal Evans:

As developers, most of us are optimists. We look at a problem and say “yeah, I can solve that”. Most of the time, we are right, we can solve that, but not usually in the timeframe we originally estimate.

So when we tell a customer/client/family member “Yeah, I can build that this weekend”. In our mind, we mean it. We honestly think the project is simple enough to be built in a weekend. It rarely is though.

Remember Clock time !=Calendar time It’s not enough to say “This project will take 2 weeks” if you have other projects you are working on in those two weeks. Make sure you tell your customer/client/family member/boss/neighbor how many hours it will take to accomplish the task, and how long it will take you to slot those hours into your schedule.

To this I would add: Do not estimate in hours. Estimate in days or weeks. If you quote 120 hours and it goes to 144 hours, the client will freak out. If you quote 15 work days and it goes to 18 work days, they’ll be a lot less bothered by it. If you quote 3 work weeks and it goes over by 3 work days, it won’t even register. It’s all the same amount of time, but the framing is different.

And regarding developers being optimists, this is so true. I regularly point out to junior developers that they are insufficiently pessimistic. A highly-intelligent developer finds it easy to rationalize after-the-fact why things didn’t go as planned. Quoting from Modernizing Legacy Applications in PHP in reference to starting a project over from scratch:

Overconfidence, insufficient pessimism, ignorance of history, and the desire to be one’s own customer all lead developers easily into rationalizations that “this time will be different” when they attempt a rewrite.

These are all totally natural behaviors for developers, especially the very talented ones. The mark of an professional is to realize before-the-fact that unforeseeable circumstances are going to ruin your perfect plan, and then to make very broad allowances for the unforeseen. Those are the kinds of practices that embed themselves only with painful experience. I have used a rule of one day per controller method per 2 developers for a long time now, and it has served me well.

Afterword

Are you overwhelmed by a legacy application full of spaghetti includes and global variables? Do you want to improve the quality of the code, but don’t know where to begin or how to proceeed? My new book, Modernizing Legacy Applications in PHP, gives step-by-step instructions on how to get your code under control and keep your application running the whole time. Buy the early access version now and get free updates as it is completed, or sign up on the mailing list below for more information and a free sample chapter.

Sign up for Modernizing Legacy Applications in PHP:

First Name Email

Modernizing Legacy Applications in PHP: Early Access

I have had several requests for early access to my new book, “Modernizing Legacy Applications in PHP,” as it is being written. I’m happy to say that as of today, that wish is granted. You can purchase the book in its ongoing state at leanpub.com/mlaphp for the low-low price of $39 ($49 recommended).

Once purchased, each new update to the book is free. The book has not yet had the benefit of formal editing, and is only about 35% complete at this point. But at 60+ pages, it already has a ton of valuable material. You can see what I mean by reading the free sample chapter.

After you purchase the book, please feel free to provide feedback! You can reach me on Twitter @pmjones. I’ll do what I can to include suggested improvements in future releases.

You can read more about the book and sign up for the mailing list at mlaphp.com. Also, if you are professional reviewer and want to write a review of the early-access version, be sure to contact me for a coupon to get a review copy.

Framework Tradeoffs For Beginners: Product Creation vs Program Maintenance

Phil Sturgeon at his blog, writing about product creators who neither know nor care much about programming as a discipline:

One of my close friends … is also a businessman, with a startup that is about to launch. …

He does however have literally no interest in becoming a world-class programmer. He barely even wants to code, but he can thanks to frameworks like Laravel.

… He’s written an awful lot of extremely good applications – that work – and that has made him some money. Ship ship ship.

… Does he know what separation of concerns means? Ha.

Is his code SOLID? Nope.

Is the Laravel application he made unit-testable? … no.

Is it going to function well enough to get him to his next round of funding? Absolutely. Is he going to have to throw the whole thing away? Not at all.

Frameworks are great for beginners, who literally could not possibly smash together a series of random components if they wanted to.

Phil’s post focuses on the joyful, proud moments of creation that lead to business success, whether in terms of venture funding or continued sales. In this essay, I want to focus on what happens after that, when that initial creation passes into other hands to be maintained.

The Great And Awful Thing About PHP

The great thing about PHP is that almost anyone can use it. The language and some of the frameworks based on it, such as CodeIgniter and its most-recent ideological descendant Laravel, make amateur and early-career(*) programmers productive in ways they could not be otherwise.

But the great thing about PHP is also the awful thing about PHP, and that is that anyone can use it. The beginner programmer who has been made productive by his framework-of-choice feels great pride and elation at coding an application that “works.” Soon, though, the poor practices embdedded in his work due to his inexperience will find their way through to the product presentation and affect the business. The code “works,” but not so well as first thought. The codebase now has to be maintained in order to remedy the flaws and shortcomings displayed by the product.

If the beginner programmer is the one who has to do this maintenance, and is the one to feel the pain of maintaining his own applications, then he will learn to improve his development practices. If he instead goes on to other responsibilities, he will leave behind what is most likely a mess for others to inherit. Going on to other responsibilities is almost always what happens when the business gets its “next round of funding.”

What Happens After Funding

Phil asks if the business is “going to have to throw the whole thing away” at that point and responds in the negative. Well, of course the business owners won’t discard the codebase. It doesn’t matter how bad the code happens to be, because the entire business is now dependent on it as developed by that original inexperienced programmer. Throwing it out and starting again would likely kill the business. No, what will happen is that the funding will be used to hire a team of more experienced developers to fix, add features to, and scale the code developed by the beginner programmer.

Because they enable amateurs to operate beyond their existing capabilities, frameworks like CodeIgniter and its cousins tend to make product creation easier at the expense of making program maintenance harder. (Note the difference between the concerns of the product and those of the program.) Some folks will argue this does not matter. Once the product owner gets funding, he can pay professionals to deal with the problems he created on the way to his successful round of funding.

If You’re So Smart …

From a financial standpoint, and perhaps even from an economic standpoint, it’s easy to see enabling-via-framework as a positive. Indeed, the product creator may justify his failures of good programming practice by substituting the product popularity and continued rounds of funding as a marker of success. Complaints from the development team about the codebase quality are met with variations of “If you’re so smart, how come you’re working for me?”. But from a programming practices standpoint, enabling-by-framework too often leads to pain and frustration on the part of the maintenance programmers, who are now saddled with the baggage of an amateur.

“Well, that’s their job!” comes the reply. True enough, but that does not change the fact that the codebase is terrible and tough to work with. Think what a team of developers could do with a codebase built with better practices at the time of its creation.

Footnote

(*) If one considers a professional programming career to span 20 years or more, I think it’s fair to say a developer can be considered “early-career” even with as many as 6-7 full-time years of experience in the field.

Afterword

In my 30-odd years of programming (half of that in PHP), I have been the developer in charge of improving a maintenance mess so often that I am now writing a book about how to modernize legacy applications in PHP. In it, I give step-by-step instructions on what to do and in what order. I hope it can reduce the pain that others have to suffer with their own similar codebases. Sign up below for a free chapter, updates related to publication, and more.

Sign up for Modernizing Legacy Applications in PHP:

First Name Email

Aura.Cli 2.0.0-beta1 Released

The Aura.Cli package provides the command-line equivalents of web request and response objects. The Context (request-equivalent) object allows insight into the $_ENV, $_SERVER, and $argv values, along with a Getopt object that lets you build and then parse flags and options passed at the command line. The Stdio (response-equivalent) object provides access to to the standard input/output/error streams.

Via .

The Aura.Cli Package

The Aura.Cli package provides the command-line equivalents of web request and response objects. The Context (request-equivalent) object allows insight into the $_ENV, $_SERVER, and $argv values, along with a Getopt object that lets you build and then parse flags and options passed at the command line. The Stdio (response-equivalent) object provides access to to the standard input/output/error streams.

Via http://auraphp.com/blog/2014/01/11/aura-cli-2beta1/.

Aura.Sql_Schema 2.0.0-beta1 Released

Wrapping up this week’s “one release a day” series is the 2.0.0-beta1 release of Aura.Sql_Schema. You can download it directly or install via Composer and Packagist.

The Aura.Sql_Schema package contains PDO-based tools to read table and column information from a database. If you already use PDO, or if your database abstraction layer of choice uses PDO under the hood, you can feed that PDO object to the Schema object and start reading your table and column information. (Because it is typehinted to PDO, this means the Schema can use an Aura.Sql v2 ExtendedPdo object as well.) The package supports MySQL, PostgreSQL, SQLite, and Microsoft SQL Server.

Via Aura.Sql_Schema 2.0.0-beta1 Released.

Aura.Web 2.0.0-beta1 Released

Our “one release a day” series continues with the 2.0.0-beta1 release of Aura.Web. You can download it directly or install via Composer and Packagist.

Whereas the v1 package included controllers, renderers, and other functionality, the v2 package provides only Request and Response objects… You can read more about the distillation of these concerns into separate packages here.

As a side note, you can see from the timing of these recent releases that Aura libraries are completely independent from each other. There’s no subtree-split or extract-and-build-for-release processing; each library is completely contained in its own repository, making individual releases through our admin script a trivial matter.

via Aura.Web 2.0.0-beta1 Released.