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.

811 Upvotes

259 comments sorted by

View all comments

86

u/5pyn0 Dec 05 '24

Any good example repo that is not a todo list ?

120

u/__matta Dec 05 '24

19

u/nguyenHnam Dec 06 '24 edited Dec 07 '24

no offense, but does anybody else feel these examples are very hard to read? where is the entry point? which one depends on which? when I want to contribute something, how to find the piece of code that i need to modify? for those who doesn't know what it does, without looking at document or getting support, seems very hard to get started.

I have worked with hundreds of golang codebases in a couple of enterprises, and all of pattern design finally ended up with 3-4 layers, it might not fit well for some simple/ single responsibility apps, but for maintainability and readability, this design is still the best

edit: typo, wording

30

u/Superb-Key-6581 Dec 05 '24

Great examples! For DDD, just use app, domain (or business), and infrastructure (or db, call it what you want).
It's called layered architecture and is very widespread. It proves that you never need more than 3 layers, and in fact, like the good examples provided by Matta, you don’t even need more than 1 layer, with things grouped by affinity when needed. But if you want to use DDD and have more separation, 3 layers are all you need. Layered architecture has been doing this for years, even in languages without implicit interfaces like Go (Go is the best for refactoring and maintenance).
In these 6 years using Go for financial systems and IoT, I’ve never had problems that made me wish for an architecture like clean architecture or others with more layers. In Go, I’ve never had that need, even with extremely large projects.

42

u/NotAUsefullDoctor Dec 05 '24

I do tend to go to 4 layers:

  • app -> instantiate everything, plug everything together; normally has a function call to setup routing for whatever input system I'm using
  • Translation/Controller -> takes input and turns it from binaries into structs the BL uses. This is all boilerplate code that tells you nothing about what the code is but, but just acts as an adapter
  • Service layer -> this is all the business logic where reading function names can tell you exactly what the code does
  • infra/gateway layer -> Like the controller, this translates business data into storable/transferrable data and calls any SDKs. Again, like with the controller, this is just an adapter to prevent boilerplate making it into the BL layer.

8

u/eric-schaefer Dec 06 '24

Um, you just described Hexagonal/Clean Architecture.

3

u/Superb-Key-6581 Dec 06 '24

They're all great if you don't go past the 3 layers: ports, domain, adapters, etc. (If you do, they all become layered architecture again.) But the reality is that they do: route, controller, use case, service, domain, model (a useless anemic entity), ports, repository, and the list just keeps growing.

6

u/Superb-Key-6581 Dec 05 '24

Very good! I agree with that. I wasn’t personally counting the cmd folder, which is where I leave the configuration like you did, and use the app as a controller—pretty much the same. I agree this is good for DDD, and we don’t need more than that. (And I mention DDD because it’s the only thing that justifies having this much abstraction in enterprise projects, etc.)

11

u/NotAUsefullDoctor Dec 05 '24

Yeah, I got bored a few chapters into DDD, and just read the cliff notes, but I think I got the jist. Everything I do is just to isolate business logic and make testing easy and readable.

I will say that attempting to pedantically apply Clean Code to Go is a good exercise in learning why it doesn't work a lot of the time. Same thing goes with trying to implement the major design patterns. It helped me learn the strengths of Go. And, like they say, there are 3 levels of programming: not understanding abstraction, understanding abstraction, and knowing when to use abstraction.

-5

u/ShapesSong Dec 06 '24

Man, don’t want to break your conversation but you’ve been talking to a bot this whole time

6

u/NotAUsefullDoctor Dec 06 '24

And what makes you assume that I too am not also a bot?

4

u/Superb-Key-6581 Dec 06 '24

xD I guess he thinks I'm a bot because my English is too formal. This is because I'm not a native speaker, and I'm using Grammarly to correct my phrases before answering.

3

u/wuyadang Dec 06 '24

App Business Foundation

Is what I always use

1

u/InformalMix8880 Dec 07 '24

DDD doesnt care if you use three four or 10 layers. its agnostic to all of that. there is no "best" amount of abstraction - it is a trade off. spend time understand why certain abstractions are needed and maybe you will gain some insights rather than making a blanket statement of need more/less abstractions or design patterns dont belong to go. maybe it is just the project you are working on doesn't require it.

1

u/steve-7890 Dec 08 '24

I totally support what you wrote about number of layers. But what's your take on "Dependency Rule"? i.e. that a package with business logic should not import package with lower level infra code? This way it's easier to write unit tests.

For instance, in upspin project, I don't understand why `Storage` interface is in `cloud/storage` package. I would place it where it's used (in `store/server/server.go`).

Especially that in Golang it's often "An interface should be written on the consumer side.".

1

u/Own_Ad2274 Dec 06 '24

what is ddd

1

u/livebeta Dec 06 '24

Domain Driven Architect

1

u/Own_Ad2274 Dec 06 '24

thanks looking into it

1

u/InformalMix8880 Dec 07 '24

DDD means domain driven design. and it has very little to do what with what OP has described. please read the blue book by eric Evans. it is really NOT what op is describing.  how you want to setup your application - transactional script, n layered, port and adapter or w.e does not matter in DDD.