A PSR-7 Web Router Implementation, and Bookdown Documentation

From the Aura blog:

Our first 3.x package is now available for review, a PSR-7 implementation of Aura.Router. It includes some feature upgrades such as custom rules and more powerful route definitions.

On a side note, the package documentation uses Bookdown for its documentation. You can see the generated documentation here. Bookdown allows us to keep documentation sources in each library repository. We can then collect them all into a single “book” on the Aura site using a bookdown.json file with remote “content” elements.

Read the rest at the Aura blog.

Separate The User Interface Repository From The Core Application Repository

tl;dr: Keep the core application (“model”, “domain”) code repository separate from the user interface (“controller/view”, “action/responder”) code repository; use a dependency manager in the user-interface repo to bring in the core-application repo.


Nihal Sahu asked on Twitter, “How do you ‘personally’ go about building an application? What Structure?” This post is my longer-than-140-characters response.

Obviously I’m a fan of Action-Domain-Responder as a pattern for web-based user interfaces. (ADR treats the request/response cycle itself as a user interface. The HTML/CSS/JS/etc that goes into the HTTP body is just one part of the presentation half of the user interface; ADR reminds us that the HTTP headers are part of the presentation, too.)

But ADR, and MVC, and the other user-interface patterns – they are not an application architecture in and of themselves. The “Domain” in ADR and the “Model” in MVC are just entry points into the underlying core of the overall application architecture. In a way, the “Action/Responder” and “Controller/View” portions of the UI are not the big deal in the application; the big deal is the underlying core. That’s where the real work happens.

With that in mind, one first thinks the right approach would be to separate the User Interface from the Core Application. This is obvious and uncontroversial; separation of concerns is a central tenet of good architecture.

What might be controversial is my extended advice regarding that approach. I don’t suggest a merely “logical” separation of concerns so that Action/Controller classes don’t have Domain/Model code in them. I suggest a “physical” separation. In other words:

Separate the User Interface repository from the Core Application repository.

Yes, I mean that you should have two code repositories for your application. Let’s explore that idea for a minute.

The first repository, the Core Application one, contains no user-interface code at all. No HTTP, no standard input/output, nothing. It expects to receive input in an interface-independent way, and it delivers output in an interface-independent way. Note that it receives the input. It has to be sent to the Core Application in some way, not read from the interface (no superglobals!). The injected input could be via method parameters, a plain old PHP array, an input object provided by the Core Application, a Command object provided by the Core application, etc. Likewise, the output could be via anything provided by the Core Application, such as a Model object, a Domain Payload, or something else. It is completely independent from any user interface code and can be tested on its own.

The other repository, the User Interface one, contains your “Action/Responder” or “Controller/View” (or “Command/Stdout”) code. There is no business logic at all. All it does it reformat the user input to something the Core Application will recognize, pass it to the Core Application, and receive back some output from the Core Application, which it reformats for presentation to the user.

But if the two repositores are “physically” separated, how can the User Interface get access to the Core Application? Composer becomes your best friend in this case. In the User Interface codebase, add "require": { "project-name/core-application": "dev-develop" } to composer.json. Issue composer update and voila: your Core Application is now available to the User Interface. The User Interface depends on the Core Applicatiion, but the Core Application has no dependency on the User Interface.

What’s great about keeping the repositories fully separated from each other is that it enforces developer discipline. It becomes difficult to put Core Application code in the User Interface code. Any attempts to do so are immediately obvious, and everyone watching can see it happening. It becomes harder to justify to yourself “I’ll add it just this one time” (and thus keeping off that particular slippery slope).

The tradeoff is that you now have to coordinate changes across two code repos. Breaks in the Core Application will break the User Interface. The disconnection can be a positive overall, since you can version the Core Application separately from the User Interface, but in practice it does mean you have to be more attentive to change management.

One more thing about keeping the User Interface “physically” separate from the User Interface in this way is that you start thinking differently about frameworks. I have begun to think that our vocabulary for describing frameworks in PHP land is insufficiently varied. MVC and ADR do not describe “application frameworks” – they might describe User Interface frameworks, but there’s no word for Core Application frameworks. Maybe they need their own separate framework term.

Aura 3 Plans

From the Aura blog:

  • The Past

    • Aura 1.x framework packages will see no new releases, and may be archived.

    • Aura 1.x library packages are near the end of active development; to prevent orphaning and end-of-life, ownership and authority over them they may be transferred to interested parties.

  • The Present

    • Aura 2.x packages that are currently stable will remain the center of development attention, with some modifications to Composer and PHPUnit support files, and with added testing on PHP 7.

    • Aura 2.x packages that are not currently stable will not see stable 2.x releases; they will become 3.x candidate packages.

  • The Future

    • Aura 3.x packages will target PHP 5.6, and additionally test on PHP 7.

    • Aura 3.x library packages will be allowed to depend on interface packages, though not other implementation packages.

    • Aura 3.x will not provide a framework under the Aura name, although the 2.x framework should be able to use 3.x components. Frameworks of Aura packages may be provided as separate projects.

    • Aura 3.x and later packages will have independent major version release cycles.

Read the entire post here.

Using Aura.Html with League\Plates

Aura has its own native PHP template package, Aura.View, a direct descendant of Savant and Solar_View, as well as a cousin to Zend_View.

The v1 Aura.View package used to include a helper system. Once we realized that there was no reason to tie the helper system directly to the view system, we released the helpers as a standalone Aura.Html package. This means the helpers can be used in any PHP presentation code, framework-based or otherwise.

As an example, let’s try integrating the helpers with Plates, a relative newcomer in the native PHP templating world. Plates allows you to register functions with its template engine, which means we can pull individual helpers out of Aura.Html and drop them into Plates, like so:

<?php
$plates = new League\Plates\Engine('/path/to/templates');
$helper = (new Aura\Html\HelperLocatorFactory())->newInstance();

$plates->registerFunction('anchor',     $helper->get('anchor'));
$plates->registerFunction('anchorRaw',  $helper->get('anchorRaw'));
$plates->registerFunction('base',       $helper->get('base'));
$plates->registerFunction('form',       $helper->get('form'));
$plates->registerFunction('img',        $helper->get('img'));
$plates->registerFunction('input',      $helper->get('input'));
$plates->registerFunction('label',      $helper->get('label'));
$plates->registerFunction('links',      $helper->get('links'));
$plates->registerFunction('metas',      $helper->get('metas'));
$plates->registerFunction('ol',         $helper->get('ol'));
$plates->registerFunction('scripts',    $helper->get('scripts'));
$plates->registerFunction('styles',     $helper->get('styles'));
$plates->registerFunction('tag',        $helper->get('tag'));
$plates->registerFunction('title',      $helper->get('title'));
$plates->registerFunction('ul',         $helper->get('ul'));
?>

Now you can use the tag helpers and form-building helpers from Aura.Html in your Plates templates. For example, if your Plates template looks like this …

<html>
<head>
<?= $this->title('My Title'); ?>
</head>
<body>
<p>Try out <?= $this->anchor(
    'https://github.com/auraphp/Aura.Html',
    'Aura.Html'
); ?>
with <?= $this->anchor(
    'http://platesphp.com',
    'Plates'
); ?> !</p>
</body>
</html>

… it will render to:

<html>
<head>
    <title>My Title</title>
</head>
<body>
<p>Try out <a href="https://github.com/auraphp/Aura.Html">Aura.Html</a>
with <a href="http://platesphp.com">Plates</a> !</p>
</body>
</html>

Try out Aura.Html today, and see how much you like it with your output system of choice. (We’re partial to Aura.View for that task, but then, we would be.)

UPDATE: As usual, Hari KT is ahead of the curve with his post on this same topic from a year ago: http://harikt.com/blog/2014/05/13/extending-plates-with-aura-html-helpers/.

UPDATE 2: Someone asked how easy it is to use Aura.Html with Aura.View. It’s 3-lines-easy: see https://github.com/auraphp/Aura.View#custom-helper-managers.

MLAPHP and N+1 Books: Half-Price Sale Starts Early!

I said a couple of days ago that the “Modernizing” and “N+1″ half-price bundle would go on sale Monday, but I finished sooner than I expected, so I’m starting the sale today. Go get the bundle here:

https://leanpub.com/b/mlasn1php

I also said that the price would be $23.99 ($39.99), but I did my math wrong. It’s actually $22.99 (suggested $28.99).

I love it when a project is early and under-budget!

A New Book About The N+1 Problem, and an Update to MLAPHP

I’ll have a new book finished and ready for you soon: Solving the N+1 Problem in PHP. Although I have written and spoken about the N+1 problem several times over the past few years, this book is an extended disstertation on the topic.

Describing the N+1 problem is one thing, and talking about the solutions in the abstract yet another. But how to diagnose and discover the problem, as well as refactoring strategies to resolve N+1 problems in your codebase? Those are something else, and they are what the new book provides, similar to the strategies I presented in Modernizing Legacy Applications in PHP. At about 40 pages of narrative and code, in many ways the new N+1 book serves as a topic-specific add-on to MLAPHP.

Speaking of which, MLAPHP is getting an update! The update is nothing extensive, mostly typo fixes and a couple of added details, all from attentive and interested readers. Current owners will receive the update for free.

So when will they be completed? Monday. And there’s a special deal involved for the week they’re finished.

MLAPHP is just about a year old, so to celebrate this new book, if you purchase both MLAPHP and the N+1 book as a bundle next week, they will each be about 50% off. That’s a total of $23.99 $22.99 (suggested $39.99 $28.99) for both books, with a 45-day money-back guarantee backed by Leanpub.

After the sale week, they’ll go back to their normal prices, so this is your chance to get a bigger bang for your buck. Of course, the new N+1 book is only $5.99 (suggested $7.99), so it’s not exactly a bank-breaker in the first place.

More updates when the new book and the update are finalized!

UPDATE (Fri 20 Mar): The bundle is now available at https://leanpub.com/b/mlasn1php. Go get it while you can!

Bookdown: DocBook-Like HTML Output From Markdown

From bookdown.io:

Bookdown generates DocBook-like HTML output using Markdown and JSON files instead of XML.

Bookdown is especially well-suited for publishing project documentation to > GitHub Pages.

Features include:

  • Automatic table-of-contents generation as index pages at each hierarchy level

  • Custom index-page titles via JSON configuration

  • Automatic numbering of page headings

  • Automatic previous/next/up navigation headers and footers

  • Multi-page hierarchical output

  • Loading of remote content files via HTTP

  • Templated output for theming

  • Overridable page processing, especially for rendering

Bookdown can be used as a static site generator, or as a way to publish static pages as a subdirectory in an existing site.

Continue reading

MVC and ADR are User-Interface Patterns, Not Application Architectures

N.b.: I am the author of the Action-Domain-Responder paper referenced in this article.

In his post on MVC alternatives (including Action-Domain-Responder), Anthony Ferrara makes a claim that is central to his discussion. While I agree with much he says in that and related articles, I believe that one claim is in error, and while it does not discredit the essay as a whole, replacing the erroneous claim with a more accurate one gives the essay a different flavor.

The central mistake I think Anthony makes is near the end of this post, where he states (in talking about MVC, ADR, et al.) that “All Pretend To Be Application Architectures.” That assertion strikes me as incorrect.

While it may be that developers using MVC may mistakenly think of MVC as an application architecture, the pattern description itself makes no such claim. Indeed, Fowler categorizes MVC as a “Web Presentation Pattern” and not as an “Application Architecture” per se.

Sure, MVC is described in book called “Patterns of Enterprise Application Architecture”, but MVC itself is a presentation pattern within an application architecture. Here’s another example of the distinction: we would not call “Table Data Gateway” an application architecture, even though it too appears in the same book. It is a data source pattern within an application architecture.

Fowler’s categorization and description of MVC define it pretty clearly as a user interface pattern. ADR, as a refinement of MVC, is likewise a user interface pattern. Neither is an application architecture in and of itself, although they are the outermost part of an application architecture. So when Anthony’s article states elsewhere that ADR’s “coupling to HTTP that it becomes difficult to make a non-HTTP interface” my response is “Well, obviously – it’s a user interface pattern centered around HTTP.”

Anthony then goes on to say:

And that’s the biggest reason all of these “patterns”, “architectures” and “concepts” are a bad joke. They solve the easy problem, and throw the hard problem over the fence.

MVC, ADR, et al., solve a user-interface problem. That may be an easy problem for Anthony to solve, but to say that user-interface patterns “throw the hard problem over the fence” strikes me as starting from the wrong set of expectations. MVC and ADR, as user-interface patterns, aren’t supposed to be dealing with core business logic in the first place.

It might be better to say that the underlying application that is presented through the user interface is not really the user interface’s problem in the first place. The user interface code probably should not care too much about the internal operation of the underlying application code. If it does, then the application code is bubbling up too far into the user interface.

In summary, I think the assertion that “All Pretend To Be Application Architectures” is just not an accurate categorization. It would more correct to say that “All Are User Interface Patterns, Not Entire Application Architectures” – or, even better, that “Developers Frequently Misunderstand Them To Be Application Architectures”.

This is why you should always use braces on conditionals

In issue 65 on Aura.Router, Optional parameters not working as expected?, we can see that the problem was this piece of code from the issue reporter:

if(isset($this->route->params["id"]))
    echo "id = " . $this->route->params["id"] . "<br><br>";
if(isset($this->route->params["function"]))
    echo "function = " . $this->route->params["function"] . "<br><br>";
if(isset($this->route->params["third"]));
    echo "third = " . $this->route->params["third"] . "<br><br>";

Look at that last if statement: it ends in a semicolon. Although the line beneath it that is *intended* to be the body of the if statement, as indicated by the indentation, it is *not* the body of the if statement. It gets executed no matter the outcome of the if condition.

That kind of thing is really tough to debug.

Instead, if we use braces on all conditionals, regardless of how short or long the body is, we get this:

if(isset($this->route->params["id"])) {
    echo "id = " . $this->route->params["id"] . "<br><br>";
}

if(isset($this->route->params["function"])) {
    echo "function = " . $this->route->params["function"] . "<br><br>";
}

if(isset($this->route->params["third"])) {
}

echo "third = " . $this->route->params["third"] . "<br><br>";

Then it’s very easy to see what’s going wrong.

That is one reason Aura adheres to PSR-2; it incorporates that rule, along with many others, that makes it easier to know what to expect when reading code. Anything unexpected becomes a signal that something may be wrong.

What’s The Difference Between A “Pivot Table” And An “Association Table”?

An “association table” is a table that joins other tables in a many-to-many relationship. For example, if an Article can have more than one Tag, and each Tag can be placed on one or more Articles, then they are in a many-to-many relationship. To associate them to each other, we need a third table through which we can join them.

-- one end of a many-to-many relationship
CREATE TABLE article (
    article_id INT,
    title VARCHAR(255),
    body TEXT
);

-- the other end of a many-to-many relationship
CREATE TABLE tag (
    tag_id INT,
    name VARCHAR(255)
);

-- an association table mapping articles and tags to each other
CREATE TABLE article_tag (
    article_tag_id INT,
    article_id INT,
    tag_id INT
);

In ORM terms, we might say each Article “has many” Tags “through” the ArticleTag association, that each Tag also “has many” Articles “through” the ArticleTag, and finally that each ArticleTag “belongs to” an Article and that it “belongs to” a Tag.

When writing SQL to find the Tags for an Article, or to find all the Articles that use a specific Tag, we join the ArticlesTags table to get the associated entity IDs. The SQL looks something like the following:

-- select all the tags for an article
SELECT tag.*
FROM tag
JOIN article_tag ON article_tag.tag_id = tag.tag_id
WHERE article_tag.article_id = ?

-- select all the articles that use a tag
SELECT article.*
FROM article
JOIN article_tag ON article_tag.article_id = article.article_id
WHERE article_tag.tag_id = ?

This pattern is called an association table mapping.

On the other hand, a “pivot table” is a cross-tabulation query, frequently used in spreadsheets. You can see more about pivot tables through Google. In short, the idea is to build a query, and convert the rows into columns by grouping the rows in a particular way. These kinds of queries generally involve some conditionals and calculations to group the query results; you can see some examples here.

In summary: if you are joining tables to each other in a many-to-many relationship, the table that maps the relationship is an association table. If you are doing a cross-tabulation to convert rows into columns, you are working with pivot table.