[HN Gopher] Microservices - Please, Don't (2016)
       ___________________________________________________________________
        
       Microservices - Please, Don't (2016)
        
       Author : h3mb3
       Score  : 72 points
       Date   : 2022-09-11 18:40 UTC (4 hours ago)
        
 (HTM) web link (riak.com)
 (TXT) w3m dump (riak.com)
        
       | brad0 wrote:
       | I reacted to this headline quite negatively. Reading the article,
       | it's actually quite reasonable. It's trying to cut through all
       | the incorrect reasons microservices/service oriented architecture
       | is adopted. Kudos to that!
       | 
       | IMO service oriented architectures should be adopted when your
       | engineering organisation has gotten too large to manage a
       | monolith.
       | 
       | The service interface generally can't be modified after it's
       | available. You can do the same with a monolith but it's harder to
       | enforce.
        
       | revskill wrote:
       | The issue with these articles, is, they assumed, bad architect
       | divided wrong domains into "wrong microservices", then concluded,
       | "microservice" is bad strategy.
       | 
       | Step 1: Understand the domain first.
       | 
       | Step 2: Use microservice for each domain.
       | 
       | If you failed at step 1, step 2 is wrong.
       | 
       | Monothlich architecture just "skips" step 1, and use one big fat
       | service for all.
        
         | drewcoo wrote:
         | > bad architect divided wrong domains into "wrong
         | microservices", then concluded, "microservice" is bad strategy
         | 
         | The more advanced someone is in their career, the less likely
         | they are to personally take responsibility for failure.
         | 
         | https://thecontentauthority.com/blog/what-does-it-is-a-poor-...
        
         | and0 wrote:
         | I don't think it's that simple. As he states, domains change
         | and requirements change. Or maybe you find value providing
         | something adjacent to or on top of the domain you're working
         | in. I can't imagine a situation where this doesn't happen to
         | some extent, except in the absolute simplest of domains.
         | 
         | I also strongly agree with the author in that network i/o and
         | distributed transactions (sagas) are huge blockers for all but
         | the most mature organizations. In my experience microservices
         | that aren't in completely isolated domains slow development
         | significantly and accrue much more tech debt, though admittedly
         | these weren't the most mature organizations. You could argue
         | that they simply did it wrong (and, oh BOY, they most certainly
         | did!!), but to some extent these practices need to address that
         | programmers aren't perfect.
        
         | 8note wrote:
         | Use a microservices for each domain is step 3.
         | 
         | Step 2 is to set up your organization so that single teams can
         | own those domains.
         | 
         | This is where the difficulty making good microservices lies -
         | your code will match your org structure, and microservices
         | makes future changes to that harder
        
       | preommr wrote:
       | My crazy advice: Build a monolith as microservices.
       | 
       | By which I mean focus on Domain Driven Development, focus
       | strongly on modularity even when, and this is the key part, it's
       | not required because it's in a monolith.
       | 
       | There are a great deal of advantages to microservices like teams
       | being able to focus on a subset that can still be accomplished
       | with a well designed monolith. While still avoiding the biggest
       | headaches with microservices like managing a crazy network of
       | deployments, across multiple environments where teams don't have
       | the neccessary discipline to communicate.
       | 
       | If at a certain point scalability does become a big enough issue,
       | then it's much more manageable to segment what's needed (and even
       | transition back if needed). It still might take months, but the
       | quality of the transition is much higher.
        
         | candiddevmike wrote:
         | Try to build your app as if you're going to reuse as much as
         | possible in another app. This will make you think about clear
         | boundaries and keeping things as standalone as possible.
        
         | jen20 wrote:
         | > Build a monolith as microservices
         | 
         | This is a case of applying Phillipe Kruchten's 4+1 Views of
         | Architecture slightly differently, such that logical,
         | development and process views are not tightly coupled to one
         | another - and works very well!
        
         | rco8786 wrote:
         | > By which I mean focus on Domain Driven Development, focus
         | strongly on modularity even when, and this is the key part,
         | it's not required because it's in a monolith
         | 
         | Here, here! If I had a dollar for every team I've seen adopt
         | micro services as a solution to code modularization I'd have
         | several dollars.
         | 
         | "Hey our code could be cleaner and our git repo seems to be
         | getting big"
         | 
         | "Sweet let's inject the network in between everything"
        
         | gabereiser wrote:
         | This is a great approach. I like to add "macroservices" into
         | conversations around this because I think it sums up the end
         | state better. It's not micro. It's an entire billing system. It
         | just only has API's and not a front-end. Integrate it. That's a
         | macroservice. Or a service that handles the subscription,
         | billing, and entitlements as one. That's a macroservice and
         | that's totally acceptable.
         | 
         | What kills me is when there's a monolith that breaks when other
         | teams commit code. If I have to stash changes and deal with
         | merge conflicts outside my team, it needs to be broken up.
         | 
         | Worry about scaling when you have a need to scale.
        
           | ManuelKiessling wrote:
           | You might find the concept of Self-contained Systems, or SCS,
           | interesting:
           | 
           | https://scs-architecture.org/
           | 
           | Disclaimer: I helped with the concept a tiny bit.
        
           | ecshafer wrote:
           | Macroservices are the way to go. Currently I work on a system
           | that is a macroservice basically. We have more than one team
           | working on the service which is great, since that means on-
           | call rotations, upgrades, etc are much more reasonable.
           | Having 50 people on a service really takes work off compared
           | to 6, and there is a lot less reinventing the wheel. As long
           | as the CICD pipeline is solid there really isn't any issues
           | with a lot of teams working on the same code base.
           | 
           | As you say having a "Billing" service is much better than
           | what you would typically see in a microservices architecture
           | that you'll have a Billing-Stripe, Billing-Visa, Billing-
           | Invoices, and so on, creating a web of dependencies.
        
             | gabereiser wrote:
             | Exactly. So long as merge conflicts stay within the team
             | (i.e. your macroservice is logically divided within the
             | code, models and services aren't just thrown into a
             | _models_ and _services_ package or folder. I really detest
             | merge conflicts when I can 't track the work or have to
             | reach out to another team to discern intent.
             | 
             | Having microservices for billing where you have Billing-
             | stripe, Billing-visa, would make me want to scream. Why not
             | a generic abstract or interface and those are simply
             | implementations _within_ the billing service? Macroservices
             | FTW.
        
       | lr4444lr wrote:
       | Gotta keep the "devops" teams employed, though!
        
       | yonixw wrote:
       | > Fallacy #5: Better for Scalability
       | 
       | > [The assumption: only by - ] .. packaging your services as
       | discrete units .. [you can] via .. Docker .. [achieve] horizontal
       | scalability.
       | 
       | > However, it's incorrect ... [to assume it can] only .. [with a]
       | microservice.
       | 
       | Interesting, how monolith can do the same?
       | 
       | > You can create logical clusters of your monolith
       | 
       | > which only handle a certain subset of your traffic.
       | 
       | Oh... so MS... but with extra steps. lol. not to mention we
       | usually care about the DB scale also, which is harder to scale as
       | a monolith with segmented traffic.
        
         | KronisLV wrote:
         | > Oh... so MS... but with extra steps.
         | 
         | Not quite: since with monoliths that are deployed in parallel
         | or have sets of functionality behind feature flags, you're
         | still dealing primarily with one codebase and each instance
         | should be able to service requests on its own, instead of
         | making further network requests across N other instances.
         | 
         | I actually wrote more about this a while ago, "Moduliths:
         | because we need to scale, but we also cannot afford
         | microservices": https://blog.kronis.dev/articles/modulith-
         | because-we-need-to...
         | 
         | A single codebase will generally be easier and quicker to
         | develop against (up to a certain scale), since you don't need
         | so much "internal glue" code between your microservices
         | (network calls and error handling, data type marshalling etc.).
         | 
         | That said, personally I'd prefer microservices for other
         | reasons - so that I could let old parts of the overall system
         | (possibly developed by others) not get in the way of progress,
         | such as not being able to update the application/service to JDK
         | 11/17 because of a PDF library only runs on JDK 8 or something
         | like that.
         | 
         | Furthermore, if you work on a project for long enough, the slow
         | startup and compile times of a large monolith (without the
         | modularization at least, which might not be possible to ensure
         | in certain stacks), the high resource usage and possibly
         | sluggish performance, the numerous approaches that have been
         | utilized to get something like logging or scheduled processes
         | over 5-10 years of development clashing with one another and
         | many other things will just get very annoying and painful to
         | deal with.
         | 
         | Being able to spin up a new service with whatever is easy to
         | work with for the particular case, making it your own little
         | corner of the overall system with good tests and arguably good
         | code (at least for now) is really nice. Until you have 20 of
         | these services, written by people with varying
         | approaches/standards and it's a mess again.
         | 
         | I think there's really no winning with either approach, each
         | has their benefits and shortcomings.
         | 
         | > not to mention we usually care about the DB scale also, which
         | is harder to scale as a monolith with segmented traffic.
         | 
         | This is a fair point!
         | 
         | Though I think that GitLab recently split their database across
         | the boundary of CI functionality and everything else, which was
         | a pretty good example of how far you can get with a single DB
         | (no doubt with replication/clustering and standby instances
         | though): https://about.gitlab.com/blog/2022/06/02/splitting-
         | database-...
         | 
         | In contrast, forgoing something like foreign keys and ending up
         | with distributed transactions (sagas or similar), having to
         | enforce your own data consistency etc. can be asking for
         | trouble before you actually need to care about scaling and
         | split everything up so much.
         | 
         | It's probably a matter of choosing whichever approach works for
         | your scale now and will work for you in the near future.
        
           | drewcoo wrote:
           | There is no reason microservices can't be in the same
           | codebase. In fact, for things like infrastructure and testing
           | that may need to touch more than one service at a time, it's
           | incredibly useful to have a monorepo.
           | 
           | I need a t-shirt: monorepos, not monoliths!
        
         | CHY872 wrote:
         | It's not necessarily much in the way of extra steps. The
         | Elasticsearch Cloud-on-K8s operator IMO does this quite well.
         | 
         | You define 'node sets' which each play a role in the cluster.
         | Node sets can have tags applied to them, and this affects the
         | procedures they run.
         | 
         | For example, you could say:
         | 
         | 1. Let's have a node set of 3 master nodes. 2. Let's have a
         | nodeset of 10 hot data nodes, backed with SSDs and tagged with
         | 'hot'. 3. Let's have a nodeset of 5 cold data nodes, backed
         | with HDDs and tagged with 'cold'. 4. 4 client nodes for load
         | balancing.
         | 
         | You could also say - let's have 3 nodes that play all roles.
         | 
         | On startup, each node starts only the parts of the app that
         | correspond to the roles it's playing.
         | 
         | It's fairly seamless and I think this model would expand quite
         | nicely to 'business logic' services
         | 
         | Anecdotally, have seem some people attempt to retrofit a poor
         | man's version of this model into their microservice in response
         | to e.g. performance problems.
        
       | fibonacc wrote:
       | I would recommend just using SAM or Chalice for MS on AWS and
       | layering on Step Functions/Fargate/ECS Anywhere for hybrid setups
       | if you are not using Kubernetes. The only difference is that you
       | are coupled to AWS but if you are already have been using AWS for
       | everything else, its very natural and easy to just learn a new
       | product and integrate it to your existing infra setup on AWS.
       | 
       | CDK is also another interesting tool in that you can create
       | classes that handles existing series of scaffolding and
       | automation and it feels naturally code like but drift detection
       | still requires improvement vs Terraform's.
       | 
       | If you work for a large company where they have mandated
       | Kubernetes then obviously its gonna be difficult but I am seeing
       | a trend where companies are starting to "hedge" their bets as K8
       | projects take far longer to get to market and requires more
       | experts to keep it going so I'm half heartedly learning
       | Kubernetes, especially on the back of my mind the existing AWS
       | solutions offer far quicker time to market and accomplishes the
       | same thing.
        
       | userbinator wrote:
       | A lot of these programming fads seem to come and go over the
       | years. I've witnessed the same cycle with OOP, then FP. What a
       | lot of people don't seem to realise is that by trying to split up
       | a system into more smaller pieces in an attempt to decrease
       | complexity, it's often the case that you end up with even more
       | complexity, just hidden in the interactions between the pieces.
        
         | drewcoo wrote:
         | > it's often the case that you end up with even more
         | complexity, just hidden in the interactions between the pieces
         | 
         | That complexity is not "hidden in the interactions." It is
         | exposed by explicit interactions.
         | 
         | The original ball-of-mud system likely had lots of actual
         | hidden complexity, but it wasn't exposed so you couldn't see
         | it, test it, or reason about it.
         | 
         | The added complexity of microservices is not from its breaking
         | things into pieces, but by all of the tools needed to manage
         | those separate pieces and their interactions. With that
         | complexity comes new superpowers that weren't there before like
         | blue-green deploys. Whether or how you use those powers is up
         | to you.
        
         | rvdginste wrote:
         | > What a lot of people don't seem to realise is that by trying
         | to split up a system into more smaller pieces in an attempt to
         | decrease complexity, it's often the case that you end up with
         | even more complexity, just hidden in the interactions between
         | the pieces.
         | 
         | I think that is a good observation that I also made and I want
         | to add to that. Moving from a monolith to microservices, is
         | moving the complexity from inside the monolithic system to the
         | interactions between microservices. This means that the job of
         | developers becomes easier since a developer only has to think
         | in terms of the microservice he/she is developing and ensuring
         | that that 'simple' system externally behaves according to spec.
         | But it also means that the job of the architect becomes more
         | difficult because he/she has to get a grasp on all
         | communication (synchronously/asynchronously) between the
         | different microservices.
         | 
         | So, even though there might be more complexity overall, I do
         | believe that from the point of view of a developer, the
         | complexity is lower.
        
           | userbinator wrote:
           | Read the last paragraph of "Fallacy #4".
        
         | arrow7000 wrote:
         | Not all of these are the same. Since when is FP a fad? Would
         | you say that structured programming is a fad? Is garbage
         | collection?
        
           | duncan-donuts wrote:
           | 2015 was the year of FP. Haskell was all the rage, elm was
           | hot, large scale dismissal of OOP was in the air. To be clear
           | I don't think FP or OOP are really fads but their popularity
           | waxes and wanes. I'll see y'all in 2027 when static typing is
           | whack and everyone is going back to dynamic typing.
        
             | crazytalk wrote:
             | I could make more or less your exact statement, but
             | substituting 2015 for 2004
        
             | nine_k wrote:
             | Maybe pure FP was a fad around 2014, but practical FP, say,
             | as embodied in React, is very much entrenched and is not
             | going anywhere.
             | 
             | (To say nothing of Excel as the most widespread functional
             | reactive programming tool, but few count it as a "real"
             | programming environment.)
        
             | eropple wrote:
             | Employed practices change in response to pain points. As an
             | example, the microservices movement corresponds pretty well
             | to an era of (overly) rapid organizational growth during a
             | tech boom where a technical response to org chart problems
             | became necessary.
             | 
             | In contrast, static versus dynamic typing doesn't seem
             | likely to be so cyclical given the significant improvements
             | in usability for gradually typed systems. Dynamic typing
             | became most recently fashionable when the experience of
             | using statically typed languages was sometimes unpleasant.
             | Static typing has improved to the point where even
             | retrofits onto other systems are very very good.
             | 
             | In areas where a reasonably complete gradual typing
             | solution has emerged for a major dynamically typed
             | language, it's rapidly become or becoming standard practice
             | --Python and TypeScript being the two most obvious ones,
             | but not the only ones. (Ruby may not get there. Its core
             | implementation doesn't seem great. I wish they went with
             | Sorbet.)
             | 
             | I don't see a reason that would unwind to the point where
             | it's a serious conversation again.
        
               | mwcampbell wrote:
               | I think the most recent popular use of dynamic typing is
               | Elixir, and IMO that's because Phoenix (especially with
               | LiveView) is the most interesting server-side web
               | framework to come along in a while. Yes, you can add type
               | checking with Dialyzer, but that's optional and AFAIK not
               | a widespread default in Phoenix projects. I wish
               | something like Phoenix and LiveView was available in a
               | strongly statically typed language, but for now I just
               | make do with the dynamic typing.
        
               | eropple wrote:
               | Elixir projects not using Dialyzer is a major reason why
               | I don't use it much; I use it in my code, but not enough
               | others do to make it comfortable. At the same time, my
               | understanding is that Elixir has some pretty interesting
               | gradual typing stuff in the works right now.
        
           | chrsig wrote:
           | as a whole, interest in it comes in waves, but it never seems
           | to make it to the mainstream.
           | 
           | Many mainstream ideas are incubated in the fp world, and wind
           | up in the mainstream. for exmaple: GC, closures, higher order
           | functions. but not any of the "functional programming
           | languages" themselves.
        
         | dcu wrote:
         | OOP is still here and microservices(especially since aws
         | lambda) is just getting stronger and stronger every year
        
           | fibonacc wrote:
           | Curious as to what constitutes MS on lambda? Because whether
           | you have a dozen lambda functions where each function
           | translates to one function vs one function with multiple
           | features, the outcome is exactly the same.
           | 
           | API Gateway also muddies the water, it no longer makes sense
           | for each lambda function to maintain stuff like services
           | endpoint like in Kubernetes.
           | 
           | In fact, if you take away containers, you can completely
           | achieve orchestration without Kubernetes. Simply use Step
           | Functions to coordinate lambda functions or even better,
           | avoid it altogether and have one lambda function coordinate
           | the orchestration procedurally.
           | 
           | My bet is that as time goes on and companies realize the
           | overhead from kubernetes and "cloud independence mandate",
           | they will drive more business towards AWS, in particular
           | Fargate is rapidly progressing, as well as ECS Anywhere
           | allows you to run hybrid setups with complete ease and
           | without the headache from Kubernetes.
           | 
           | Just realizing these things as I learn kubernetes and I keep
           | thinking "wait I can just X from AWS and this bypasses the
           | need for kubernetes altgoether" but seems like companies are
           | already knee deep.
        
           | userbinator wrote:
           | Yes and so is FP; but you don't have the same level of
           | dogmatism for OOP that was prevalent in the mid 90s up to
           | early 2000s.
           | 
           | As for microservices, the fact that it's great for cloud
           | services nickel-and-diming you probably makes them likely to
           | remain popular as long as the cloud computing propaganda
           | continues to have effect.
        
         | EGreg wrote:
         | I actually think that's the key to building a system that
         | everyone can reason about.
         | 
         | The goal is to have these isolated "modules" where stuff is
         | heavily interconnected, and the connections between modules are
         | well-defined protocols. Then people know the common denominator
         | of what's possible and build with that. Meanwhile, you can
         | prove things about the behavior of a module and uss the
         | isolation between modules to prove various properties about the
         | whole system.
        
       | oneplane wrote:
       | My advice: there is no universal services advice, therefore,
       | don't adopt (or un-adopt) things just because someone wrote about
       | it. At the same time: don't ignore pain, regardless if it's
       | because you're too big, too small, too segregated or too
       | monolithical.
        
       | tacitusarc wrote:
       | I find the hackernews obsession with bashing micro services
       | tiresome. We get it, your organization didn't need the scale/had
       | a relatively simple problem/couldn't solve bad code by doing
       | microservices.
       | 
       | Sometimes it's the wrong call. Sometimes it's the right one. It's
       | not a panacea, obviously. Can't we just use our expertise and
       | judgement to determine the correct architecture? There are always
       | trade-offs. Our job is to rigorously evaluate them and make a
       | good decision, not blindly follow or dismiss any particular
       | implementation.
        
         | bottlepalm wrote:
         | Tired of being bashed in the office when devs out of college
         | want to rewrite everything because it's not microservices.
         | Microservices are web scale they say.
         | 
         | Management not knowing any better pour resources into
         | microservices because it's so hot. Devs who want promotions go
         | over engineer new systems.
         | 
         | Devs who resist are made to maintain the entire monolith
         | themselves, or find another job because they are not team
         | players.
         | 
         | Eventually there ends up two massive piles of code and all the
         | old and 'new' devs have left by then. Not sure what happens
         | after that, I never stayed to find out.
        
           | drewcoo wrote:
           | Why do they really want to rewrite everything?
           | 
           | I'm willing to bet that if the everything were clear and easy
           | to modify, they'd prefer not rewriting everything. If it
           | "just worked," they could focus on adding customer-pleasing,
           | revenue-increasing functionality, a far more reliable path to
           | promotion.
        
             | bottlepalm wrote:
             | First everyone knows monoliths are bad. Next understanding
             | existing code is hard work, writing your own new code is
             | perfectly understandable and fun, because you're the one
             | who wrote it, and you write perfect code! It's so good you
             | don't even need to comment it!
             | 
             | The default thought process is 1. I don't understand this
             | code and business domain, 2. It is too complex, 3. We
             | should rewrite it as microservices 4. You've replace 2% of
             | the system with your microservice, 5. New devs quit because
             | your own service is now too much hassle to maintain, 6. Old
             | devs quit because you wasted enough of their time 7. The
             | org now has n+1 layers of tech debt, ready for the cycle to
             | repeat.
             | 
             | When I left n=5. 4 had a good run and we really tried to
             | keep it going. Can't fight the HN zerg sometimes.
        
       | wjossey wrote:
       | Sean Kelly (aka Stabby), is one of the most talented engineers
       | I've ever worked with, and is someone who understands the
       | challenges and pitfalls of architecture ahead of his time, as
       | this article highlights so well. To this day, I try to channel
       | Sean's approaches to design, coding, and architecture, in my own
       | work.
       | 
       | Sean is a treasure in the Boston and Golang community, and folks
       | should seek out his wisdom and guidance.
        
       | dang wrote:
       | Related:
       | 
       |  _Microservices? Please Don 't_ -
       | https://news.ycombinator.com/item?id=13167188 - Dec 2016 (122
       | comments)
       | 
       |  _Microservices - Please, don't_ -
       | https://news.ycombinator.com/item?id=12572859 - Sept 2016 (93
       | comments)
       | 
       |  _Microservices_ - https://news.ycombinator.com/item?id=12508655
       | - Sept 2016 (146 comments)
        
       | wintorez wrote:
       | Also, micro-frontends
        
       | CHY872 wrote:
       | There are many excellent problem solving techniques in software
       | engineering. Taken as religion, to extremes, most of these will
       | lead the zealot to destruction. Microservices have their place,
       | as do monoliths.
       | 
       | The author's most valuable point is roughly 'don't believe the
       | hype' - and that's timeless. On the specifics, they're certainly
       | right on each point, but they missed the (imo main) one of 'by
       | forcing a conceptual boundary between different pieces of the
       | application, one can build true silos around competences and so
       | scale their org more effectively'. Put simply, a 200 person
       | monolith will usually feel like it has 200 people working on it.
       | That same org split into 5 groups of 40 can be more nimble. In
       | some cases this is due to infra ('we need to get off Java 8' is
       | easier if the software can be run in 5 pieces). In some cases
       | this is due to problem scope (less intertwining of concepts
       | possible).
        
         | spaetzleesser wrote:
         | "There are many excellent problem solving techniques in
         | software engineering. Taken as religion, to extremes, most of
         | these will lead the zealot to destruction."
         | 
         | This is actually true for a lot of things like nutrition,
         | health or exercise. They start out as a useful thing but then
         | people with a big ego promote them as the solution for
         | everything.
        
       | hsuduebc2 wrote:
       | I love how these paradigmas change every two years.
        
       | atomflunder wrote:
       | Interestingly, I think that almost all of the downsides listed in
       | the article and in the comments go away if you use a good
       | framework for creating microservices (example for this: [0]):
       | 
       | No internal glue code, no overhead by writing network interfaces,
       | no slow HTTP calls (faster gRPC instead), no manual handling of
       | asynchronous tasks.
       | 
       | [0]: https://github.com/jina-ai/jina
        
       | TrianguloY wrote:
       | Moved from a monolith to a microservices project. The main and
       | almost only benefit (and the reason I asked to move) is that
       | startup time is now practically non-existent (from 8-10 minutes
       | to 30-40 seconds). This allows for faster testing and iterative-
       | programming approach, which is the type of programming I do.
        
       | beders wrote:
       | Approaches like Polylith allow you to delay any decision on how
       | or if to split up your services until you are ready. In the
       | meantime you can gradually stake out your boundaries by defining
       | suitable interfaces.
        
       | dvfjsdhgfv wrote:
       | This is part of the problem: people say "do" or "don't" or
       | "considered harmful" and suddenly this becomes a fashion
       | everybody seems to follow no matter what. I saw the same with
       | OOP, at some point it was almost a heresy to say there are many
       | cases when OO design is inefficient or problematic. You would be
       | labelled as uneducated or ignorant. For the same reason I'd never
       | use a goto at work even though I know it has some limited valid
       | uses. Etc. etc.
       | 
       | One would think that by know everybody understood that each
       | technology has its own advantages and limitations and it makes
       | zero sense to follow current trends but rather to examine the
       | project well and use the tech that fits best, regardless what
       | current "evangelists" say.
        
       ___________________________________________________________________
       (page generated 2022-09-11 23:01 UTC)