back

by alexandercrohde·10y ago·view on hn ↗
This analysis brings to the front a personal frustration, and I imagine it's not unique to me.

This article discusses some architecture techniques, but moreover, it buys into a Culture of Architecture that we don't have a word for yet. This CoA is predominant among Java engineers who worked at large, slowly-dying companies (e.g. IBM).

The issue with the CoA is that it cares more about buzzwords than quantifiable claims or objective measures. CoA was once addicted to microservices, when that model failed it'll be "all about" another, and so on. Rife with academic good-sounding CoA words that nobody can argue with like "SOLID" and such.

To be a little more concrete, "Broker topology" is a 25-cent word for a 1-cent idea (and it's not the only one, see every keyword in bold in the page, it's almost like a college textbook). There seems to be an implicit assumption in CoA that there is a finite number of architecture patterns and they must be learned by name.

Again, to be more concrete, "layered" architecture is an oversimplification of a fundamental idea (abstraction) in engineering.

This textbook-esque presentation also really misses the spirit of coding. It presents a UML (another CoA must) of "Event-Driven" architecture, then one of "Layer" Architecture, without really explaining if these can be combined or are mutually-exclusive (of course they could be combined). But by treating them as named nouns it creates a misleading and complex language around fundamental ideas.

4 comments
I violently agree, and I suspect most of HN does.

There's an associated danger though: I find that many startup hackers actively dismiss good ideas (and even entire programming languages) simply because they smell a bit of CoA.

Even the CoA crowd occasionally comes up with truly good ideas that have way more substance to them than the meaningless patterns mentioned in this article.

As an example: My personal pet peeve is the startup world's ignorance of Domain-Driven Design and CQRS (Command-Query Responsibility Segregation). If you want to make scalable backends, I really recommend you read up on CQRS, it's practical and it fits modern ideas. Most examples are in C#, but you'll survive.

For frontenders, CQRS is basically Flux on the backend, kinda sorta. It ought to be super hip right now but it isn't, and I suspect that's only because it comes from C#-o-world and has a ridiculous unpronounceable acronym.

At work I've been implementing some rough CQRS/DDD stuff for "the 2.0 system", and I'd summarize them as:

CQRS: Writes/commands and Reads/queries are fundamentally asymmetrical. Accept it and take advantage of it by having separate pipelines with different features.

DDD: Collaborate with the business-folk to discover their mental-model, and treat it and the code-model as similar co-evolving pieces. Focus on behavior and rules more than pigeonholes for data. Use Repositories to handle how RAM is not infinite, and Services for stuff you truly can't fit into meaningful objects.

> As an example: My personal pet peeve is the startup world's ignorance of Domain-Driven Design and CQRS (Command-Query Responsibility Segregation). If you want to make scalable backends, I really recommend you read up on CQRS, it's practical and it fits modern ideas. Most examples are in C#, but you'll survive.

Most starts never become successful enough to have to worry about scalability; in fact, if they do, it's almost a luxury.

I don't have experience with CQRS and event sourcing, but it does seem to come with its own share of problems, for example dealing with changes of the data model, which I suspect would happen often in young businesses.

It's very easy to do CQRS without Event-Sourcing. ES is really a separate kind of architecture-piece that's concerned with how you mutate your persisted data.

For example, at work I've got a CQRS system where the MySQL database looks pretty much like you'd expect from any other system. (Customers table, one row per customer, etc.) It's still CQRS because writes and reads occur through different paths, and writes can have side-effects to proactively-build readable data. For example, "Top 100 Happiest Customers" might be its own table--managed by application code--rather than view or query.

If you do it that way, you don't get the famed scalability; it's still limited by the scalability of the mysql backend.
Not sure exactly what capability you're referring to with the "famed" scalability, but my point is that CQRS in no way requires Event Sourcing, and offers its own set of benefits. (It's also a helluva lot easier to do, or un-do.)

In particular, CQRS helps you make a sane architecture for "read models", where certain features (say, a homepage showing a hard-to-calculate leaderboard) are simple queries against a data-source designed specifically for that feature. The backing data-source is kept up to date by application code as a side-effect of your "real work".

This means you can substantially reduce the runtime load on the database as well as reducing how much application-logic "leaks across" in triggers/procedures/views. Since your database is often the "bottleneck of last resort", this means better scalability.

The codebase is, however, very well structured to make that change later on.

You don't need to do a lot of CQRS to make future scalability a relatively simple redesign.

This frustrates me as well.

It's not just limited to the Culture of Architecture, a bunch of concepts in software seem to have similar issues (MVC vs MVVC, REST, etc). Unlike a bunch of other disciplines, there is a distinct lack of thought into what should be applied for each application problem. Electronics textbooks generally mention that a circuit is best for a specific set of applications, and talk about some of the limitations of applying the circuit (eg: very accurate voltage regulation, but does not tolerate fluctuations in temperature).

Huh, I didn't think about it until now but I'll anecdotally confirm your EE vs SWE observation. Then again, maybe I'm just far enough from the center of the EE scene that I don't get hit by as much dogma. Hard to tell.
OK, help me understand:

Is there any difference between CoA and design patterns? Sure, "Broker topology" is probably trivial, but so's Chain Of Responsibility and Decorators and everything else the Gang of Four touches on.

So, are you just as opposed to design patterns as CoA?

I want to be clear on this, I am not at all opposed to design patterns. I am not opposed to architecture. The part of CoA that bothers me is the C (culture).

That is to say: There are many great problems to solve and some reusable strategies that can be employed to solve them. However, in my experience (such as this article), many people who talk most loudly/frequently about architecture are parroting this complex and unquestioned set of assumptions and behaviors (read: culture) in a counterproductive way. Again, those behaviors include: reinventing a complicated words for simple ideas (and using them in front of audiences without defining them), creating UML diagrams even for audiences they don't expect to know UML, focusing on adding a lot of new named "patterns" to their mental book of patterns.

For example, since somebody brought it up, take CQRS. Firstly, the way Fowler and Wikipedia explain this are vastly different, if not contradictory (indicating an issue). Secondly, it can be explained (the wikipedia version) as [to quote wikipedia] "methods should return a value only if they are referentially transparent and hence possess no side effects." This has so many exceptions I wonder why it justifies its own acronym.

And the perhaps worst of all part of this culture is that members of the culture then find a need to explicitly use all of these patterns in the most verbose ways. The more obscure the pattern and the more complex, the better they feel, like a 15-year-old who just discovered a thesaurus. Pretty soon they have 3 classes named things like MessagingLoopInterpreterInterface to achieve very basic things.

I feel the same way much of the time.

However, I think much of the value of having design patterns and fancy vocabulary for architecture boils down to having simple, short names for complicated, yet common, patterns and principles.

For example, if you're being onboarded into a team of twelve to develop an already somewhat large product, the phrase "it's an n-tier application, with many of our older models' data access layers using some kind of CQRS" is immediately meaningful and useful to you, in the same way referring to 1000+ line objects as "adapters" or "aggregates" is meaningful and useful to you.

Having this vocabularly enables communication of an intended purpose and responsibility for arbitrarily large swaths of code in a way that boilerplate documentation and tests can't.

(Naturally, if you're writing something from the ground-up, or you're one of a small handful of developers on the project, the value of this is somewhere between negative and negligible, which might explain the polarization of opinion on this topic...)

Unfortunately, the Wikipedia article [1] doesn't distinguish between CQRS (command-query responsibility segregation) and CQS (command-query separation). They are entirely different concepts. Compare Fowler's CQRS article [2] to his CQS article [3].

CQS is an old OO design principle suggesting that an object's behavior is easier to reason about if every method either changes the state of the object or interrogates its current state. That's not always possible, but it's a helpful habit.

CQRS is the idea that use cases involving searching and reporting across many entities are fundamentally different from use cases involving interactions with particular entities. It is therefore sometimes worthwhile to develop separate data models for searching and reporting that are updated asynchronously.

[1] https://en.wikipedia.org/wiki/Command–query_separation

[2] http://martinfowler.com/bliki/CQRS.html

[3] http://martinfowler.com/bliki/CommandQuerySeparation.html

> it can be explained (the wikipedia version) as [to quote wikipedia] "methods should return a value only if they are referentially transparent and hence possess no side effects

This simply isn't even accurate at all; that "it can be explained" as such is just plain false.

"Architecture astronauts"