It used to be "There are no solutions, only tradeoffs."
These days, I'm feeling more a bit Bowie: "Don't listen to the crowd, they say 'jump.'"
It used to be "There are no solutions, only tradeoffs."
These days, I'm feeling more a bit Bowie: "Don't listen to the crowd, they say 'jump.'"
In which a correspondent asks about Application Services, Domain Services, and the interactions between them.
The word "service" is everywhere in my codebase. Can you suggest a naming convention, or directory structure, or other advice, regarding Application Services?
I hear you on the word Service popping up everywhere. Using the same word everywhere for different things makes it hard to differentiate between them.
Having that trouble myself, I have started using the term "Use Case" instead of "Application Service". Further, I do only one thing per Use Case, instead of doing several things in an Application Service.
I have a directory structure something like this in one project:
src/ Domain/ ... UseCase/ Draft/ AddDraft.php FetchDraft.php PublishDraft.php SaveDraft.php TrashDraft.php Post/ FetchPost.php FetchPosts.php SavePost.php TrashPost.php
Note that the naming is "human" and does not have "UseCase" suffixed on it. (More on that in a bit.)
I'm struggling to know exactly what goes in the blog Application Service and blog non-application service. Where does user authorization ("can this user create a blog?") go? Where does validation ("is the title long enough? is the publish date in the future?") go? Are those application or non-application services?
This is where the idea of a Domain Service (cf. the DDD books by Vernon and Evans) comes into play. They say those non-application services are called Domain Services.
If a non-application service is injected into other non-application services, should all this be moved out of the Application Service? If so, the Application Service don't really then contain anything as far as I can see.
Whereas an Application Service presents a face to the world outside the Domain, the Domain Service is internal to the Domain. As such, it's totally fine to have that non-application Domain Service get injected into different Application Services (and for Domain Services to be used by other Domain Services).
And yes, that means eventually the Application Service may then contain almost nothing at all except calls to coordinate different Domain Services. I think this is part of a natural progression:
You used to put everything in a Controller method or Action class; then you extracted the domain logic into an Application Service.
Next, different Application Services needed to do the same things over and over; you extracted the shared logic to different Domain Service classes.
Finally, you realized that your Application Service could just use one or more Domain Service objects in a lot of cases.
Voila: all non-trivial logic is down in the Domain now. The Application Service coordinates between one or more of those Domain Services, then presents a Domain Payload back to the user interface.
And how would I name those non-application services?
I have started keeping my Domain Services grouped with their "main" entity or aggregate. For example:
Domain/ Content/ Draft/ Draft.php DraftRepository.php PublishDraftService.php UseCase/ ...
Note how the naming is still "human", but does have a "Service" suffix.
The problem I ran into was that, because they did not have differentiating suffixes, the "PublishDraft" Use Case had the same class name as the "PublishDraft" Domain Service. That caused local name conflicts when they were both used together. I would have had to alias one or the other in the
use statement, so I figured I might as well give one (or the other) a class name suffix, to preempt name conflicts.
In this project I went with a suffix on the Domain Service, but might just as well have gone with a "UseCase" suffix on the Use Cases instead. (You get to pick your tradeoffs here.)
How do you suggest I communicate these possible failures between two different Domain Services? One option is to use the Domain Payloads, but again I think they are only for returning to the action, not between domain services. So the only other option I see really is domain-specific custom exceptions, but I've always felt a bit weird about domain specific exceptions. Do you have any thoughts on this? Any obvious option I'm missing?
I would say: definitely not via Domain Payload while within the Domain. The Domain Payload is always-and-only for reporting back across the boundary to the User Interface layer. Instead, use Exceptions within the domain, and/or some other domain-specific notification or messaging system while within the domain.
Also, to keep domain-level exceptions from escaping to the User Interface layer, the Application Services should have a catchall for exceptions emanating from the Domain. For example, add some wrapper or decorator logic on your Application Services to catch all exceptions from Domain activity, and that catchall can return a Payload (with the error in it) back to the calling User Interface code.
See the Reddit conversation about this post here.
"How do we know if something is canceling vs. ordinary criticism?" I came out with a list of six things, kind of the warning signs of canceling. If you've got two or three of these, it's canceling and not criticism.
First: Is the intent of the campaign punitive? Are you trying to punish the person and take away their job, their livelihood, and their friends?
Second: Is the intent or predictable outcome of the campaign to deplatform someone and to get them out of the position that they hold where they can speak/be heard and out of any other such position?
Third: Is the tactic being used grandstanding? Is it not talking to the person about their point of view? Is it basically virtue signaling, posturing, denunciation, and sort of ritual in nature?
Fourth: Is it organized? Is it in fact a campaign? Is it a swarm? Do you have people out there saying, as is often the case, "We've got to get Nick Gillespie off the air" or "We've got to get this asshole fired"? If it's organized, then it's canceling. It's not criticism.
Fifth: A certain sign of canceling is secondary boycotts. Is the campaign targeting not only the individual but anyone who has anything to do with the individual? Are they not only saying, "We think what Nick Cannon is saying on the air is inappropriate"; are they going after the company by saying to boycott it? Are they going after his friends and professional acquaintances? If there's a secondary boycott to inspire fear so that no one wants to have anything to do with the guy for the fear that they'd be targeted, that's canceling.
Sixth: Is it indifferent to truth? Well-meaning criticism is often wrong, but if it's wrong, you're supposed to say, "Oh, gee. I'm sorry that was wrong." You're supposed to pay attention to facts. Cancelers don't. They'll pick through someone's record over a period of 20 years and find six items which they can use against them. This is what literally happened to [Harvard psychologist] Steve Pinker. Tear them out of context and distort them, and if they're corrected on them, they'll just find six other items. That's not criticism. That's canceling. These are weapons of propaganda.
(Adapted from my talk Your Project Needs a Code of Conduct, OR ELSE.)
Leftists often say, regarding free speech, that "You might get freedom of speech, but you don't get freedom from consequences!" All right, then, let's go with that for a minute. What are the proper consequences for political speech that you disagree with?
Is it to burn down my house?
Is it to call in a SWAT team to shoot me?
Is it to drag me out of my car and beat me to death?
Is it to punch me in the face when you see me on the sidewalk?
Is it to cancel my financial accounts so that I cannot purchase goods and services?
Is is to threaten my employers into firing me, so that I cannot provide for myself and my family?
Is it to eject me from voluntary organizations?
The proper consequences for political speech that you disagree with, are for you to offer opposing political speech; that is, not "incitements to action" but "arguments."
NumFOCUS found I violated their Code of Conduct (CoC) at JupyterCon because my talk was not “kind”, because I said Joel Grus was “wrong” regarding his opinion that Jupyter Notebook is not a good software development environment.
Joel (who I greatly respect, and consider an asset to the data science community) was not involved in NumFOCUS’s action, was not told about it, and did not support it.
NumFOCUS did not follow their own enforcement procedure and violated their own CoC, left me hanging for over a week not even knowing what I was accused of, and did not give me an opportunity to provide input before concluding their investigation.
I repeatedly told their committee that my emotional resilience was low at the moment due to medical issues, which they laughed about and ignored, as I tried (unsuccessfully) to hold back tears.
The process has left me shattered, and I won’t be able to accept any speaking requests for the foreseeable future.
I support the thoughtful enforcement of Code of Conducts to address sexist, racist, and harassing behavior, but that is not what happened in this case.
Jeremy exhibits Stockholm Syndrome in his article. He extols the virtues of Codes of Conduct, even though the actual application of this COC left him "shattered."
As with Communism, this is not a problem of the COC "not being applied properly" or "not being done right." Social Justice codes of conduct cannot be "applied properly" or "done right" according to their popularly-assumed intentions. They are always-and-only in place to allow the exercise of arbitrary power over others. The way the COC was enforced here is the norm, not the exception.
I am proud to announce Argo, a flat-file static-site blog authoring and building system. It generates your site on your own computer, then syncs it to a remote host via Git or rsync.
(This very blog uses Argo, and has done so for quite a while.)
My blogging software for the longest time was WordPress, and it was good enough, though it was subject to intermittent denial-of-service and other attacks. Mitigating those was not a lot of trouble, but it was occasionally time-consuming, and never a welcome distraction.
Then I started hearing about, and witnessing, the Social Justice cancellation and de-platforming of some of my regular online readings, all built using WordPress. One day there, next day gone -- and on contacting the authors, I learned they did not keep their own local backups. All their content, all their hard work and creative product, had all disappeared because of the Social Justice indignation of the week.
Now, it is well-known that I am no fan of Social Justice. I am not a Leftist of any stripe: not a Democrat, Progressive, Socialist, Communist, or Marxist. I think that Marxism in its various forms is a great enemy of Western civilization.
That attitude makes me persona non grata in much of the technology and programming world. It makes me a target for censorship and cancellation under whatever cover is deniably plausible, by people who signal their tolerance for anything other than their outgroup.
I began to consider what might happen to my own blog, how it too might be disappeared one day. How might I defend it against the attacks of Marxist and Social Justice zealots?
Thus was born my motivation to create Argo.
Argo's key features are centered around resilience:
You always keep all your content on your own computer. All your posts, images, and other files are stored locally.
The software itself runs on your own computer, not in the cloud, so you always keep the code behind the software.
Argo uses flat file storage, not a database; among other things, this makes it easy to use standard file tools, and to bundle assets with posts.
Argo generates static HTML and JSON for publishing, and does not use a server-side programming language; this keeps the hosting requirements minimal.
Publishing is a matter of syncing to a remote host, whether by Git or rsync. If a host cancels you, you can change your local configuration, and sync all your content to the new host.
These basic features make Argo-based blogs resistant to cancellation, censorship, and de-platforming. Yes, a host might still surprise you by pulling your account, but the consequences are far less drastic: none of your content has been lost.
Some of the incidental and technical features are:
Content items are written in Markdown; HTML and WordPress pseudo-html are supported as well.
The content items do not use "YAML frontmatter"; instead, content metadata is stored in an
argo.json file, and the body content is stored in
The flat-file storage structure is exactly the same as the published URL structure, resulting in a easy-to-understand information architecture. When syncing, the remote file structure will be identical to the local file structure.
The build system generates not only HTML files, but also JSON files; this means that each content item is accessible through a read-only API. (Try out the JSON resource for this post.)
All configuration settings are stored as JSON files.
It is still early days for Argo, and there is a lot left to do.
The administrative interface is spartan at best, and needs some UI/UX love.
Likewise, the WordPress import feature appears to work properly, but I'd like to have more test cases around it.
There is no built-in commenting system (nor do I think there could be, given that it runs locally and not on a server) but integrating an external commenting service ought to be achievable.
Those are just some of the highlights.
Of course, Argo is not only for those who are interested in being cancel-resistant. Use Argo because you want to keep local control over your own content.
To understand the Nazis accurately, you have to read their own quotes and propaganda. The story told by the Nazis themselves depicts a very different party than what modern journalists would like us to believe. The Nazi (National Socialist German Workers Party) or National Socialists as they called themselves, had the following five key characteristics:
The Nazis were a self-proclaimed socialist movement that called for the end of capitalism, abolishment of non-labor income (interest and finance), and proposed an all-powerful central authority to regulate the market
Racial identity politics was used to identify an oppressor class (Jews), that embodied both the evil nature of capitalism and the anti-German nature of communism
Strong nationalistic pride was a core pitch to the people to justify a stronger central authority
The party used militant radical socialist activists to harass businesses and political enemies with acts of violence
Limitations on free speech and removing access to dissenting views
Via American Thinker.
Aside: the evils of National Socialism stemmed not from the nationalism, but from the socialism.
Also: the only way the Nazis are to your right, is if you are a Communist.
You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is.
Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest.
Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. (Even if n does get big, use Rule 2 first.)
Fancy algorithms are buggier than simple ones, and they're much harder to implement. Use simple algorithms as well as simple data structures.
Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.
Pike's rules 1 and 2 restate Tony Hoare's famous maxim "Premature optimization is the root of all evil."
Ken Thompson rephrased Pike's rules 3 and 4 as "When in doubt, use brute force.".
Rules 3 and 4 are instances of the design philosophy KISS.
Rule 5 was previously stated by Fred Brooks in The Mythical Man-Month. Rule 5 is often shortened to "write stupid code that uses smart objects".
Copied from http://users.ece.utexas.edu/~adnan/pike.html.
Whenever I think about what did the most damage to internet culture over the past ten years, xkcd 1357 comes out on top. Not Twitter. Not Facebook. This simple comic.
Freedom of speech isn't just a legal assurance that congress shall make no law abridging it. It is also a set of cultural norms rooted deeply in a long lineage of hard won ideas.
Replace "Pravda" with any institutional media organ in the United States, and "the Party" with Leftists/Progressives/Democrats/Marxists/Socialists/Communists:
The Front Page belongs to the Party. Everything you see on the front page is the Party's most important messaging. The more prominent the article, the more you can assume that it is pure propaganda. Front Page above-the-fold articles are nothing but propaganda.
Most of the time there will be actual journalistic facts reported in the story. You know, the Who/What/Where/When stuff. This will in general be in articles buried inside the newspapers, and/or buried in paragraph 25 (under the assumption that most people will scan the front page and maybe the first 2 or 3 paragraphs). Our trainer essentially taught us to read Pravda backwards, starting from the end and working our way back towards the front.
Things that really, really bother the Party will be prominently displayed. Things that really really bother the Party will be on the front page, above the fold. While this seems to contradict item #1 above, it really doesn't. Sure, the actual contents of the article are nothing but propaganda, the information to be gleaned is that the subject is something that the Party hates.