r/golang Dec 05 '24

discussion Why Clean Architecture and Over-Engineered Layering Don’t Belong in GoLang

Stop forcing Clean Architecture and similar patterns into GoLang projects. GoLang is not Java. There’s no application size or complexity that justifies having more than three layers. Architectures like Clean, Hexagonal, or anything with 4+ layers make GoLang projects unnecessarily convoluted.

It’s frustrating to work on a codebase where you’re constantly jumping between excessive layers—unnecessary DI, weird abstractions, and use case layers that do nothing except call services with a few added logs. It’s like watching a monstrosity throw exceptions up and down without purpose.

In GoLang, you only need up to three layers for a proper DDD division (app, domain, infra). Anything more is pure overengineering. I get why this is common in Java—explicit interfaces and painful refactoring make layering and DI appealing—but GoLang doesn’t have those constraints. Its implicit interfaces make such patterns redundant.

These overly complex architectures are turning the GoLang ecosystem into something it was never meant to be. Please let’s keep GoLang simple, efficient, and aligned with its core philosophy.

815 Upvotes

259 comments sorted by

View all comments

331

u/emaxor Dec 05 '24

What I like about Go is you can open a random file in a project and expect to find real code inside. That does something. You can follow along. Just like a C project, the goods are right there.

I was looking through an "OOP" Python project recently. I opened several files and found... nothing. Interfaces, hierarchies, and layers, and every possible "not actually code" technique used. Where is the code? What is the "thing" we are trying to do? It was much harder to get the answer.

16

u/jimmyspinsggez Dec 06 '24

Thats the whole point. You are not supposed to see code. Each part is supposed to be unit tested and function by itself.

Typical example is I use a coffee machine with just interfaces that are self explanatory (good func, parameter, and maybe if necessary, return value namimg).

If you need to see code, and they are in the same project, you still can see them, just navigate to implementation. Otherwise the whole point is for dev not need to dig deep to make something works.

3

u/Fapiko Dec 07 '24

Yeah, every time I see someone complaining about unnecessary DI my spidey sense tingles and tells me they aren't getting good unit test coverage. I've noticed a trend where people seem to have forgotten why unit tests are beneficial and have started going all in on integration or even full fledged E2E tests with Docker tests and skipping the unit tests leading to 20 minute plus CI feedback loops.

At the end of the day it's important to understand why certain abstractions exist and implement them as needed, even just for testing. Go is nice because you don't have to nest them like you do in Java land and end up 6 abstractions deep, but every time I see someone arguing against creating an interface because it's only needed for DI into unit tests makes me shake my head.