Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> In my opinion, not allowing circular dependencies is a great design choice for building large programs.

I have a hobby project with maybe 20 packages involved. Circular dependencies were getting harder and harder to solve.

What worked in this situation was to separate the whole hairball into two layers. The packages in the app layer could import packages from the utilities layer, but not vice-versa.

This introduced enough structure to simplify the removal of circularities and prevent new outbreaks.



But, don't you know you can't have a utils package either?

A package must implement one functionality, and it must be clear from the short import name what that functionality is.

A package is also the only way to enforce visibility (and often, with that, other useful properties like immutability).

So packages can't be too big, or too generic, but they can't also be too small, or too specific.

I also have 2 (or 3?) layers, and a utils package, and the packages are huge, and yet I need various cheats to allow cyclic dependencies, and have some repetition with other tricks to avoid some of it.

It's the real world, and guess what, the very well designed standard library does… all of the above too.


> But, don't you know you can't have a utils package either?

Oh, I know. What I have is over half a dozen such packages named "*utils".


What do you mean by "can't"?

"Can not" means "not possible", but it's clearly possible.


I obviously meant "can't" not RFC 2119 "MUST NOT".

I could list more sources, but I'll just leave you with these:

https://go.dev/blog/package-names

https://google.github.io/styleguide/go/best-practices#util-p...

https://dave.cheney.net/2019/01/08/avoid-package-names-like-...

The Google style guide is worth a read through, as the subsequent point recognizes the difficulties around package size. It can make sense to have a package with a single function, and it can almost make sense to stuff your entire program/library in a single package.

The two rules work that exacerbate this tension are precisely visibility and no cyclic dependencies.

The perfect is the enemy of the good. Forbidding cyclic dependencies is one such case, IMO.




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

Search: