Paul M. Jones

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

Why I think xkcd is wrong about Free Speech

The xkcd cartoon conflates the particular and narrow protections of the 1st Amendment of the U.S. Constitution with the older, broader, more general (and, if we’re honest, somewhat nebulous) principle of freedom of speech.

It is a great mistake to imagine that these things are the same. Doing so ignores the existence of non-governmental forms of censorship, including corporate censorship (e.g. internet filtering), and popular censorship via the tyranny of the majority -- or, for that matter, the tyranny of powerful minorities!

In an open society, you personally are supposed to recognize the freedom of others to speak. Via Why I think xkcd is wrong about Free Speech – Pat Kerr – Medium


Sinatra, Bogart, and "Cool"

[Frank Sinatra] is idolized -- and obsessively studied and massively imitated -- not merely for the creation of art but for the creation of public self, for the confection of affect and biography that the artist projects onto the national screen.And what Frank Sinatra projected was: cool. And here is where the damage was done. Frank invented cool, and everyone followed Frank, and everything has been going to hell ever since.

In America, B.F., there was no cool. There was smart (as in the smart set), and urbane, and sophisticated, and fast and hip; but these things were not the same as cool.

The pre-Frank hip guy, the model of aesthetic and moral superiority to which men aspired, is the American male of the 1930s and 1940s. He is Humphrey Bogart in The Big Sleep or Casablanca or Archie Goodwin in Rex Stout's Nero Wolfe novels.

He possesses an outward cynicism, but this is understood to be merely clothing; at his core, he is a square. He fights a lot, generally on the side of the underdog. He is willing to die for his beliefs, and his beliefs are, although he takes pains to hide it, old-fashioned. He believes in truth, justice, the American way, and love. He is on the side of the law, except when the law is crooked. He is not taken in by jingoism but he is himself a patriot; when there is a war, he goes to it. He is, after his fashion, a gentleman and, in a quite modern manner, a sexual egalitarian. He is forthright, contemptuous of dishonesty in all its forms, from posing to lying. He confronts his enemies openly and fairly, even if he might lose. He is honorable and virtuous, although he is properly suspicious of men who talk about honor and virtue. He may be world-weary, but he is not ironic.

The new cool man that Sinatra defined was a very different creature. Cool said the old values were for suckers. Cool was looking out for number one always. Cool didn't get mad; it got even. Cool didn't go to war: Saps went to war, and anyway, cool had no beliefs it was willing to die for. Cool never, ever, got in a fight it might lose; cool had friends who could take care of that sort of thing. Cool was a cad and boastful about it; in cool's philosophy, the lady was always a tramp, and to be treated accordingly. Cool was not on the side of the law; cool made its own laws. Cool was not knowing but still essentially idealistic; cool was nihilistic. Cool was not virtuous; it reveled in vice.

Before cool, being good was still hip; after cool, only being bad was.

Much though I would like to be Frank, I might actually be more Bogart. Source: Things Worth Fighting For - ABC News


The Lost Tools of Learning

To learn six subjects without remembering how they were learnt does nothing to ease the approach to a seventh; to have learnt and remembered the art of learning makes the approach to every subject an open door.

Source: The Lost Tools of Learning


Use Rhetoric To Sell Books

Selling is a pure popularity contest. Awards are pure popularity contests. Once you get over that, the better your friends will do and the better you will do.

...

When you want to do something with the culture, post your memes, be funny, be quick witted. That’s all that matters in this internet era. If you want to see change, it starts there.

Source: How I Use Rhetoric To Sell Books | The Writings of Jon Del Arroz


Domain Logic and Email Templates

From an email conversation with a reader:

Hi Paul,

I’ve been following your writing and examples about the ADR pattern for some time now. It’s taken me awhile to wrap my head around it but ADR has really added a lot of structure to my code and I’m thankful for your work!

One dilemma that I’ve been struggling with is how to organize emails that are sent out by my service classes. Currently my business logic dictates when to send an email and most of them contain html and text templates. It just feels wrong to include those email templates within the Domain. Do you have any recommendations? Any help you can provide would be greatly appreciated.

In a somewhat related question - Recently I’ve been organizing my “views” folders within the folders of their parents (Http, Mail). I think I based it on your ADR example on github. Do you still prefer this method or do you lean towards organizing within a “resources” folder?

My intuition is that you are right to keep the email templates out of the domain.

In a way, sending an email as part of a web request/response cycle is like sending two responses: the normal HTTP response, and the email response. With that in mind, it might make sense to think of the HTML + Text email templates as part of a presentation layer. Or, as a combination of infrastructure (the email-sending client) plus presentation (the templates). That would be how to think about the separation of concerns there.

Here’s an example of what that separation of concerns might look like in a package directory structure:

resources/
    templates/
        web/
            # web page templates
        email/
            message-1/
                message-1.html
                message-1.txt
            message-2/
                message-2.html
                message-2.txt
src/
    Domain/
        AppService/
            FooAppService.php
            BarAppService.php
        EmailInterface.php
        # ... other domain classes
    Infrastructure/
        DataSource/
            # ... mappers, tables, etc
        Emailer.php # implements Domain\EmailInterface
    Web/
        Foo/
            FooAction.php
            FooResponder.php
        Bar/
            BarAction.php
            BarResponder.php

The specifics of directory structure are not important, as long as you see that the Emailer class is separated from the Domain application services (or use cases, or whatever).

The Emailer class, for its part, might be a facade [1] that coordinates between a “real” emailer (e.g. Swiftmailer or PhpMailer) and a template class, to put together and then send the email. You could configure the Emailer class with the template location (resources/templates/email/*) and inject it into your application service (which depends on the EmailInterface).

Now, sending emails inline as part of the web request might be fine in a lower-traffic situation. But as volume scales up, this kind of separation will make it easy to extract all email-sending to a workers. Then the Emailer can queue emails to the workers instead of sending them inline with the web request; the email-sending can become the job of a queue worker, and the template work will go there instead.

As far as where to put templates for views:

The extended example ADR code on GitHub is a few years old at this point. I still think it’s a reasonable setup, especially for people transitioning out of pseudo-MVC toward ADR, but it might do well to receive an update (or some examples of variations).

I don’t prefer any particular method or structure on where to put templates. Sometimes it makes sense to keep templates near the things using them, sometimes it makes sense to collect them all one place. The needs of the system, and the prior experiences of the developer(s), will be the deciding factor as far as I’m concerned. I had PHP-PDS on the brain when I replied, so the pds/skeleton with its “resources” directory was at hand.


[1] A real facade, not a Laravel one. ;-)


Camille Paglia: On Trump, Democrats, Transgenderism, and Islamist Terror

The cold biological truth is that sex changes are impossible. Every single cell of the human body remains coded with one's birth gender for life. Intersex ambiguities can occur, but they are developmental anomalies that represent a tiny proportion of all human births.In a democracy, everyone, no matter how nonconformist or eccentric, should be free from harassment and abuse. But at the same time, no one deserves special rights, protections, or privileges on the basis of their eccentricity. The categories "trans-man" and "trans-woman" are highly accurate and deserving of respect. But like Germaine Greer and Sheila Jeffreys, I reject state-sponsored coercion to call someone a "woman" or a "man" simply on the basis of his or her subjective feeling about it. We may well take the path of good will and defer to courtesy on such occasions, but it is our choice alone.

A wide-ranging interview. Source: Camille Paglia: On Trump, Democrats, Transgenderism, and Islamist Terror | The Weekly Standard


No, You’re Not More Likely to Be Killed by a Right-Wing Extremist than an Islamic Terrorist

The fact that the two deadliest attacks upon the U.K. in recent memory were at the hands of Islamic terrorists is not simply pub trivia. I mention it because when these apologists for Islam get bored of claiming that jihadists are incessantly and inexplicably lying about their religious motivations, they invariably engage in the crass exercise of throwing around skewed data in a desperate attempt to deemphasize the danger posed by Islamic terror. this is not due to some well-meaning concern for people worrying unnecessarily, or to ensure that counter terrorism strategy is accurately focused upon the most serious threat, it seems rather to be a tactical attempt to prioritize the protection of odious 7th century folklore over the welfare of real human beings.

In the not uncommon event of an Islamic lunatic slaughtering a crowd of innocent people, Americentric articles and tweets lying about the likelihood of this happening to you, instantaneously begin to surface, like gunk from the ocean floor after a depth charge detonation.

Source: No, You’re Not More Likely to Be Killed by a Right-Wing Extremist than an Islamic Terrorist – Areo Magazine


How Oxford and Peter Singer drove me from atheism to Jesus

Christianity, it turned out, looked nothing like the caricature I once held. I found the story of Jacob wrestling with God especially compelling: God wants anything but the unthinking faith I had once assumed characterized Christianity. God wants us to wrestle with Him; to struggle through doubt and faith, sorrow and hope. Moreover, God wants broken people, not self-righteous ones. And salvation is not about us earning our way to some place in the clouds through good works. On the contrary; there is nothing we can do to reconcile ourselves to God. As a historian, this made profound sense to me. I was too aware of the cycles of poverty, violence and injustice in human history to think that some utopian design of our own, scientific or otherwise, might save us.

Source: How Oxford and Peter Singer drove me from atheism to Jesus - The Veritas Forum - The Veritas Forum


Can a scientist believe in the resurrection?

To explain how a scientist can be a Christian is actually quite simple. Science cannot and does not disprove the resurrection. Natural science describes the normal reproducible working of the world of nature. Indeed, the key meaning of “nature”, as Boyle emphasized, is “the normal course of events.” Miracles like the resurrection are inherently abnormal. It does not take modern science to tell us that humans don’t rise from the dead. People knew that perfectly well in the first century; just as they knew that the blind from birth don’t as adults regain their sight, or water doesn’t instantly turn into wine.

Source: Can a scientist believe in the resurrection? Three hypotheses. - The Veritas Forum - The Veritas Forum


Controllers and Domain Exceptions

A few months ago I had a great email conversation with a correspondent about how to handle business logic exceptions in his controller code. His message follows, lightly edited for brevity and clarity:

I think controller has single responsibility - to mediate communication between caller's context and actual business logic services. (I believe business logic services should be unaware of caller's context, be it HTTP request or CLI.)

Given that services should be unaware of who called them, they should not throw HTTP-specific exceptions. So instead of throwing a Symfony HttpNotFound Exception, the service would throw ObjectNotFound (which is HTTP agnostic) in cases where DB record could not be found.

Yet at the same time the logic that converts exceptions to HTTP responses expects HTTP-specific Symfony exceptions. This means that the exception thrown by service needs to be transformed into Symfony exception.

One of solutions I see to this is that the controller could take that responsibility. It would catch domain exceptions thrown by service and wrap them into appropriate HTTP exceptions.

class FooController
{
    public function fooAction()
    {
        try {
            $this->service->doSomething('foo');
        } catch (ObjectNotFound $e) {
            throw new NotFoundHttpException('Not Found', $e);
        } catch (InvalidDataException $e) {
            throw new BadRequestHttpException('Invalid value', $e);
        } // ...
    }
}

The downside I see with this approach is that if I have many controllers I will have code duplication. This also could lead to big amount of catch blocks, because of many possible exceptions that could be thrown.

Another approach would be to not have try/catch blocks in controller and let the exceptions thrown by service bubble up the stack, leaving the exception handling to exception handler. This approach would solve the code duplication issue and many try/catch block issue. However, because the response builder only accepts Symfony exceptions, they would need to be mapped somewhere.

It also feels to me that this way the controller is made cleaner, but part of controllers responsibility is delegated to something else, thus breaking encapsulation. I feel like it's controllers job to decide what status code should be retuned in each case, yet at the same time, cases usually are the same.

I truly hope you will be able to share your thoughts on this and the ways you would tackle this.

If you find yourself in this situation, the first question to ask yourself is, “Why am I handling domain exceptions in my user interface code?” (Remember: Model-View-Controller and Action-Domain-Responder are user interface patterns; in this case, the user interface is composed of an HTTP request and response.) Domain exceptions should be handled by the domain logic in a domain-appropriate fashion.

My correspondent’s first intuition (using domain-level exceptions, not HTTP-specific ones) has the right spirit. However, instead of having the domain service throw exceptions for the user interface controller to catch and handle, I suggest that the service return a Domain Payload with domain-specific status reporting. Then the user interface can inspect the Domain Payload to determine how to respond. I expand on that approach in this post.

By way of example, instead of this in your controller …

class FooController
{
    public function fooAction()
    {
        try {
            $this->service->doSomething('foo');
        } catch (ObjectNotFound $e) {
            throw new NotFoundHttpException('Not Found', $e);
        } catch (InvalidDataException $e) {
            throw new BadRequestHttpException('Invalid value', $e);
        } // ...
    }
}

… try something more like this:

class FooController
{
    public function fooAction()
    {
        $payload = $this->service->doSomething('foo');
        switch ($payload->getStatus()) {
            case $payload::OBJECT_NOT_FOUND:
                throw new NotFoundHttpException($payload->getMessage());
            case $payload::INVALID_DATA:
                throw new BadRequestHttpException($payload->getMessage());
            // ...
        }
    }
}

(I am not a fan of using exceptions to manage flow control; I’d rather return a new Response object. However, I am trying to stick as closely to the original example as possible so that the differences are more easily examined.)

The idea here is to keep domain logic in the domain layer (in this case, a service). The service should validate the input, and if it fails, return a “not-valid” payload. The service should catch all exceptions, and return a payload that describes the kind of error that occurred. You can then refine your controller to examine the Domain Payload and handle it however you want.

Using a Domain Payload in this way is not a huge leap. Essentially you move from a try/catch block and exception classes, to a switch/case block and status constants. What’s important is that you are now handling domain-level exceptions in the domain and not in the user interface layer. You are also encapsulating the status information reported by the domain, so that you can pass the Domain Payload object around for something other than the controller to inspect and handle.

Encapsulation via Domain Payload opens the path to a more significant refactoring that will help reduce repetition of response-building logic across many controller actions. That next refactoring is to separate out the response-building work to a Responder, and use the Responder in the controller action to return a response. You can then pass the Domain Payload to the Responder for it to handle.

class FooController
{
    public function fooAction()
    {
        $payload = $this->service->doSomething('foo');
        return $this->responder->respond($payload);
    }
}

class FooResponder
{
    public function respond($payload)
    {
        switch ($payload->getStatus()) {
            case $payload::OBJECT_NOT_FOUND:
                throw new NotFoundHttpException('Not Found', $e);
            case $payload::INVALID_DATA:
                throw new BadRequestHttpException('Invalid value', $e);
            // ...
        }
    }
}

Once you do that, you’ll realize the majority of your response-building logic can go into a common or base Responder. Custom cases can then be be handled by controller- or format-specific Responders.

And then you’ll realize all your Action logic is all pretty much the same: collect input from the Request, pass that input to a Domain-layer service to get back a Domain Payload result, and pass that result to a Responder to get back a Response. At that point you’ll be able to get rid of controllers entirely, in favor of a single standardized action handler.