Hacker News new | past | comments | ask | show | jobs | submit login

I agree with vast majority of the post, and it matches my experience. What I'm not sure I follow is the part about layered architecture, and what is offered as an alternative. The author quickly gets to a _conclusion_ that

> So, why pay the price of high cognitive load for such a layered architecture, if it doesn't pay off in the future?

where one of the examples is

> If you think that such layering will allow you to quickly replace a database or other dependencies, you're mistaken. Changing the storage causes lots of problems, and believe us, having some abstractions for the data access layer is the least of your worries.

but in my experience, it's crucial to abstract away — even if the interface is not ideal — external dependencies. The point is not to be able to "replace a database", but to _own_ the interface that is used by the application. Maybe the author only means _unnecessary layering_, but the way the argument is framed seems like using external dependency APIs throughout the entire app is somehow better.




I commented on this in another thread here.

What I read it as is don’t over-index on creating separate layers/services if they are already highly dependent on each other. It just adds additional complexity tracing dependencies over the networking stack, databases/datastores, etc that the services are now split across.

In other words: a monolithic design is acceptable if the services are highly intertwined and dependent.


If you feel like you are missing key parts of the argument, like I was, it might help to switch the view from "short" to "long" - there's a little slider on the right hand side of the screen. This adds in some paragraphs that help the piece flow better. (I'd never seen a blog post with this feature before.)


I agree. I find this part of the article weird as it has contracting statements:

> No port/adapter terms to learn

and

> we gave it all up in favour of the good old dependency inversion principle

Both use interfaces, just in different ways. We use hexagonal (ports and adapters) pattern in my project. If you asked anyone on my team to define hexagonal architecture they'll have no idea what you're talking about. They just follow the project coding patterns. There's no additional complexity.

> If you think that such layering will allow you to quickly replace a database or other dependencies, you're mistaken

I think most people do not stay at companies long enough to see the price of not abstracting away these things. That's the next developer's problem. The code tends to be tightly coupled to the libraries and frameworks used. Eventually, the projects dependencies have to be upgraded (usually due to security issues) and the migrations are usually incredibly difficult, expensive, and fragile. The product's business logic is tightly coupled with the framework and libraries used at the time. Even if the company realizes that framework has no future, they're kind of locked into their initial decision made a decade ago. At least, that's been my experience.

We have two major products at my company. Both started with the same initial framework, but the project I architected that used hexagonal was migrated to a faster and more modern framework within 4 weeks. The other product had a multi-year migration to a newer version of the same framework (and by the time it was completed is already two major versions outdated). Both products are similar in scale and code size.


I think the 'Layered Architecture' section is all over the place.

There are a lot of terms thrown around with pretty loose definitions - in this article and others. I had to look up "layered architecture" to see what other people wrote about it, and it looks like an anti-pattern to me:

  In a four-layered architecture, the layers are typically divided into:
    Presentation
    Application
    Domain
    Infrastructure

  These layers are arranged in a hierarchical order, where each layer provides services to the layer above it and uses services from the layer below it, and each layer is responsible for handling specific tasks and has limited communication with the other layers. [1]
It looks like an anti-pattern to be because, as described, each layer depends on the one below it. It looks like how you'd define the "dependency non-inversion" principle. Domain depends on Infrastructure? A BankBalance is going to depend on MySQL? Even if you put the DB behind an interface, the direction of dependencies is still wrong: BankBalace->IDatabase.

Back to TFA:

> In the end, we gave it all up in favour of the good old dependency inversion principle.

OK. DIP is terrific.

> No port/adapter terms to learn

There is a big overlap between ports/adapters, hexagonal, and DIP:

  Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases. [2]
That is, the Domain ("application") is at the bottom of the dependency graph, so that the Infrastructure {Programs, Tests, Scripts} can depend upon it.

> If you think that such layering will allow you to quickly replace a database or other dependencies, you're mistaken.

Layering will not help - it will hinder, as I described above. But you should be able to quickly replace any dependency you like, which is what DIP/PortsAdapters/Hexagonal gives you.

> Changing the storage causes lots of problems, and believe us, having some abstractions for the data access layer is the least of your worries. At best, abstractions can save somewhat 10% of your migration time (if any)

I iterate on my application code without spinning up a particular database. Same with my unit tests. Well worth it.

[1] https://bitloops.com/docs/bitloops-language/learning/softwar... [2] https://alistair.cockburn.us/hexagonal-architecture/




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: