Paul M. Jones

Don't listen to the crowd, they say "jump."

Refactoring To Action-Domain-Responder

The v1 version of the Aura framework includes a controller to handle web assets. The idea for this controller was that an Aura package might have images, scripts, and stylesheets that need to be publicly available, but in development you don't necessarily want to copy them to a public document root every time you change them. The framework dispatches all "/asset/*" routes to the asset controller, which in turn reads the requested package asset from the file system and places its contents into the response body. Performance-wise this is horrible, so in a production environment one would use a build process to copy all the package assets to a static asset server, but in a local development environment it is a valuable convenience.

Take a look at the v1 version of the asset controller. It is constructed as a Page Controller within an MVC architecture. The default actionIndex() method receives an Aura package name in the form of Vendor.Package and a trailing file path indicating the asset to load from that package, then reads that file from the package and loads it into the response body.

That v1 version is a mess. The Controller handles the response-building entirely, and there is no Model separation at all. Let's try refactoring it to an Action-Domain-Responder architecture and clean it up some for a v2 version. (For this example refactoring, we have Hari KT to thank for getting us started.)

  1. First, we need to extract the Domain portions of the code. After some discussion, we determined that the Domain here is the file-reading portions of the code. Instead of an Aura-specific Vendor.Package algorithm, we build a map of vendor/package keys that point to arbitrary directory prefixes (typically but not necessarily in a Composer installation). Finally, we figure that the caching elements would be better as part of a build process rather than on-the-fly, so we remove those caching elements; this reduces a significant portion of the Domain work.

  2. Next, we extract the response-building activity to a separate Responder class. The response-building work turns out to be relatively straightforward: if the asset has a path, that means the service found it, and we should present it as 200 OK; if not, we present it as 404 NOT FOUND.

  3. Last, we rename the Controller to an Action, and name its one-and-only "main" entry point as __invoke(). We modify the code in the Action to (1) invoke the Domain with the incoming request input, (2) place the Domain data into the Responder, and (3) return the Responder.

The end result is three classes instead of one: AssetService to handle Domain work, AssetResponder to handle the response presentation, and AssetAction to handle the incoming request and pass data from the Domain to the Responder.

Compared to the original Controller class, we clearly have more classes, and (aside from the fact that we removed the caching functionality) we likely have somewhat more code as well. But each class, and each method in each class, is relatively short, and the package overall is much more testable:

  • the AssetServiceTest is completely freed up from the Action and Responder (as it should have been in the original MVC code)

  • the AssetResponderTest does not need either the AssetAction or the AssetService, and is able to examine both the body and the headers of the response

  • the AssetActionTest does little more than to check if __invoke() returns a Responder, and see if the assigned data was retained

This separation has the effect of making the underlying components much more independent of each other and a lot easier to test. If we wanted to get really serious we would use interfaces and test doubles to fully isolate the classes.

Right now, some readers are looking at this example and wondering "How is this different from refactoring to a better-separated MVC?" The main difference in this particular example is that, in a webbish MVC setup, the work of setting response headers is generally handled in the Controller. Doing so does not give us as clean a Separated Presentation as we see under ADR. (Remember: on the web, the template is not the view; the response is the view.) In addition, to test the full response (i.e., the headers as well as the body) we would need to run the controller action code instead of just the separated presentation code.

Two final notes:

  • This example is not the only way to do Action-Domain-Responder. The Action could invoke the Responder directly, instead of allowing the calling code to invoke it. The Action might receive a ResponderFactory instead of a Responder object directly. The Responder might receive a ResponseFactory instead of a Response object directly. The Action might just be a closure in a micro-framework route. The point is that we now have a cleanly separated presentation, where the response-building work is completely extracted from the Action, and the Domain work is simiarly completely extracted from the

  • The Action returns a Responder and not a response object; this is predicated on how Aura.Dispatcher works. When the dispatcher invokes a Controller or Action, it checks the return value from that invocation; if that return value is itself invokable, the dispatcher does so recursively until the return result is no longer invokable. This means that the Dispatcher becomes responsible for invoking the Responder returned from the Action; the invoked Responder returns the completed response object.)

That is all; if you have comments on the Action-Domain-Responder paper, please leave them here or as issues out at Github.



Legacy Refactor Question: What About Singletons?

In my talk and my book on refactoring legacy PHP code, one of the early steps is to start removing globals and replace them with dependency injection (not a container, just injecting dependencies by hand.) I addressed the use of the global keyword and the $_GET (et al) superglobals, but I did not address singletons directly. I had a Reddit correspondent ask about singletons recently, and how to refactor away from them; I answered on Reddit, where you can read the full conversation.


A Round Of Aura 1.x Library Releases

Over the weekend we released updated versions of every 1.x library.

Most of these were “hygiene” releases, with docblock updates, extra tests, and minor bug fixes. However, the Router has two new methods to append and prepend route collections, and the Uri package adds support for schemeless URLs, ftp/ftps schemes, single label hosts, and an updated Public Suffix List.

Many thanks to everyone who made these releases possible, especially to Hari KT for insisting on the need for hygiene releases, and to Jeremy Kendall for his work on the Uri package.

A Round Of 1.x Releases.


Towards Reproductive Rights For Men

The most common argument against men having reproductive rights is the old “keep it in your pants” one, which we would never accept as an argument for why women should be forced into parenthood. Having sex is not consent to parenthood for women, so why should it be for men?

...

What would reproductive rights look like for men? Well, rather similar to what they look like for women. When an unplanned, unwanted pregnancy occurs, the woman, and only the woman will decide if her body will host that pregnancy to term. But even after the child is born, she may opt out of parenting that child by surrendering it for adoption. If men had the same rights, they too would be able to legally surrender their rights and allow the mother or any other individual to assume legal responsibility for the child.

via Let’s Talk About Reproductive Rights And Why Men Should Have Them Too | Thought Catalog.


Bush Admin Blows CIA Cover = "treason"; Obama Admin Does Same Thing = "a mistake"

Many observers seem satisfied with the White House's explanation that the incident was just a regrettable error. And that is indeed what it appears to be. But such assessments represent a remarkable change in tone from the discussion several years ago, when the George W. Bush administration leaked Valerie Plame's identity as part of a bitter fight over the origin and direction of the Iraq war. Back then, it was quite common to hear the words "traitor" and "treason" used to describe top Bush officials involved in the controversy.

To be perfectly clear, this is not about Bush v Obama. It's about how reporters take sides. Via When Bushies blew a CIA cover, it was 'treason'; now, it's a mistake | WashingtonExaminer.com.



The Rise of Crown Government in America

... once you have a chief executive chosen by popular election, you are in trouble. The “extreme” measure of the legislature removing the head of state happens much more readily in parliamentary systems ... we are just about the only country without a parliamentary system that isn’t pretty far along on the autocracy spectrum.

... the problem with popular election of Prime Ministers, and especially of Presidents, is that they become much more powerful than legislatures. They have national legitimacy, they can present a unified front, and they can dominate the news media. Separation of powers is a pipedream.

via The Constitution, the President and Us | askblog.


Do Not Resign -- Make Them Fire You

Make them fire you. If you resign under pressure you have basically no legal standing. Make. Them. Fire. You. If they pressure you to resign, you should write a letter, declining to resign, declining to take any responsibility for your private, off-duty, speech and/or actions. Specifically point out that you are exercising your personal discretion to engage in political and social commentary regarding current events, that you are not willing to be subjected to a hostile work environment for your unorthodox political views, and that you are not willing to explain or defend or justify those personal political views.

Always make them do their own dirty work.

via Vox Popoli: Mailvox: employment advice.


The Template Is Not The View

As server-side web developers, we tend to think of our templating system as providing the View layer in a Model-View-Controller architecture. I have recently come to the conclusion that this is an incorrect approach. Instead, we need to think of the HTTP response as the View.

When an HTTP client makes an HTTP request, what does it get in return? It does not receive only the body of the HTTP response. The client receives the body and the headers of the HTTP response. The response as a whole is what the web application delivers as its presentation to the client.

Templating systems, as far as I can tell, deal only with the body of the HTTP response. In practice, the rest of the response is generally handled by the Controller; for example, setting the status, setting cookies, and modifying headers.

Let's say we accept the idea that the HTTP response is the View (i.e., the presentation that is delivered to the client). If we accept that idea, then for a clean separation of concerns a la SeparatedPresentation, we need to combine both the template work and the header work into their own layer. That layer needs to be completely separated from the Controller and Model.

Thus, anything that deals with the response, including the setting of headers, should be considered the View layer. If you are setting headers in a Controller, you are losing that clean separation of concerns. To remedy this, your Controller needs to hand off to a layer that builds the response on its own; this is the proper place for the tempalting system to be invoked, not the Controller.

In summary: the template is not the View. The response is the View. We should separate our concerns accordingly.

Afterword

If you like the line of thinking presented here, please check out the Action-Domain-Responder refinement of the MVC pattern. It's still a work-in-progress so be sure to leave your comments and criticism either here on this blog or as a new issue at Github.



Federal magistrate orders arrestee to apologize and recant, as a condition of bail

The arrestee alleges she was assaulted and beaten by a Federal agent; the magistrate, before he will let her post bail, wants her to recant her allegations as a condition of bail.

This seems to me clearly unconstitutional: It’s an order compelling speech, on threat of imprisonment, which would itself normally be a First Amendment violation; but on top of that, it was issued without a trial, and thus without any final factual findings supporting its validity.

I’m aware that, once someone is convicted, courts have considerable latitude to impose speech restrictions as a condition of parole or probation, and might even be able to impose speech compulsions. But that is after someone’s guilt has been proven beyond a reasonable doubt in a criminal trial. The defendant here hasn’t been convicted of anything; she continues to be presumed innocent until proven guilty.

via Arrestee alleges government misconduct; federal magistrate orders arrestee to apologize and recant, as a condition of bail.

Here's a little more, from a different article:

One agent, realizing they did not have a warrant for that address, directed other agents to leave the premises. Then, according to Branson, another agent, the one who allegedly choked Arielle Lipsen, told Branson he had to leave. At that point, Branson asked to see a warrant.

“He said, ’I don’t need to show you a F-----g warrant.’"

Branson said, "I need to see a warrant, based on the fourth amendment…"

"The agent answered ‘Oh you’re a F-----g lawyer now. We can do this the easy way or the hard way and put his finger on the trigger of his M16. That’s when I just backed up,” Branson said.

According to Branson the alleged assault to Lipsen happened in plain view, on the sidewalk in front of a residence.

“It happened outside on the sidewalk, " stated Branson, "She wasn’t even on the property. She was standing on the sidewalk.”

It only gets worse from there. Via Bold witness to alleged abuse by federal agents comes forward.