I hate go. Specifically I hate go packages. It was poorly designed. Any time you create a package in go you can’t have circular dependencies. Which makes sense right? When you make a package in rust or node or python those packages can’t have circular dependencies.
If you have two files in go or any other language, circular dependencies are usually permitted which also makes sense. It’s only packages that don’t permit this.
But guess what? You create a package in go simply by putting everything in a folder. So people when writing a go project they often make dozens of packages just by the is ocd need of organizing things into folders.
But when you organize things into folders the files in those folders aren’t project files anymore. They are different packages and you can’t have circular dependencies.
And that’s a big problem as this design conflicts with programmer instincts on how to organize things.
We organize things by meaning and name and subject matter. But simply using folders in go we are forced to organize things via dependencies and this causes a clash and makes organizing things 10 times harder than it should be in go.
Imagine I have a chicken and an egg. Chicken goes in the animal package and egg goes in the food package. It is now fundamentally impossible to make a chicken lay an egg and an egg hatch a chicken at the same time. Our tendencies to organize things via meaning has clashed with this requirement of organizing things via dependencies.
Does it make any sense at all? We probably don’t want packages to be interdependent in this way. But the stupid thing is just be creating a freaking folder we create this problem in go and it doesn’t make sense because if the files are outside of a folder you don’t hit this problem.
I would say go is actually poorly designed. I can’t think of any popular language that has this strange inconsistent problem.
It actually causes huge headaches in organizing things in go but idiot developers when they hit this circular dependency problem they literally believe the documentation when it tells them that they aren’t organizing things correctly and they need to think harder about design. So in a lot of go shops they spend an inordinate amount of time naming folders and organizing shit just to get their ocd need of organizing things by name to jive with gos requirement to organize things by dependency.
In the real world things can be in different categories and also interdependent at the same time. Go’s universe doesn’t allow this.
I’m here to tell you that It does make sense to put eggs in the food folder and chickens in the animal folder. Go is just stupid in this area, not you. Don’t believe the idiot who wrote that in the docs.
> Imagine I have a chicken and an egg. Chicken goes in the animal package and egg goes in the food package. It is now fundamentally impossible to make a chicken lay an egg and an egg hatch a chicken at the same time.
I am familiar with people eating unfertilized eggs. I am even familiar with balut. But I am not familiar with the delicacy of eating an egg as it hatches. If you eat an egg as it hatches, wouldn't that actually be eating a chick (the chicken) rather than an egg?
I suspect the real problem here is that your domain model is ill-conceived. In fact, while Go has no lack of faults, I suspect the vast majority of the complaints directed towards it come down to the limited feature set not enabling papering over bad design decisions.
I've been writing Go for about 5 years now and can confirm cicular dependency issues were typically handled buy a small refactor or considering where the borders of the domain should _really_ be
I think the issue the OC was hinting at is that the borders of the domain are forced to be the files. Having a folder for "food" and a folder for "animal" should not imply that they are in different packages by the OC's reasoning.
Perhaps both of them should be the same package, but to achieve this, you can't organise it into folders.
_This_ is what OC was complaining about. Considering where the borders of the domain should be is a second handed issue that is only due to the bad choice of having packages be determined by folder structure, which is the complaint of OC.
Right. And people conflate the issue. Especially go developers. They can’t see the difference.
They naturally create folders based off of semantic meaning instead of packaging. Then they hit the dependency issue and they think creating the folder was a domain modeling problem when really they just created the folder based off of semantic meaning and not dependencies.
The whole thing has confused go developers. They think putting things into the right folders actually has some deeper design meaning when really it’s just to make it easier for humans to find shit.
Your joking. I have a hundred food items and a hundred animal items. Cows produce milk. Chickens produce eggs. Eggs produce chickens.
It makes 100 percent sense to make two folders. Food and animals.
‘I suspect your “domain model” is ill conceived’??? You buy into that? Don’t follow what those idiots tell you.
You realize that we use these actual separations between food and animals in the real world? And now because of some design philosophy the domain model is ill conceived? The result is a more convoluted domain model to make things flow.
Actually I think this is an easier way to explain it to you. The “domain model” or aka categorization of food and animals works in reality and every other language because it’s not a bad design decision. The reason why it doesn’t work in go is because go is the bad design decision.
> You realize that we use these actual separations between food and animals in the real world?
The distinction between "animal" and "food" isn't necessarily faulty, but an egg considered to be for food and an egg considered to be for hatching are deemed distinct types in the real world. An egg from the grocery store is not going to hatch no matter how hard you coddle it. This is not the same type of egg that will hatch a chicken. Reusing the same model for both types of eggs does not work in the real world, and thus it stands to reason that it doesn't work in software either.
Revisit the model in a way that actually reflects the real world and your circular dependencies are bound to disappear.
Who said it has to be a grocery store. I’m in a farm. Some eggs I eat, some eggs I hatch. I have a food bin and an animal pen. Two different boxes for two different things.
Makes sense in the real world. Why doesn’t it make sense in go? You literally think there’s some elegant underlying principle here having to do with categorization do you? It’s mind boggling to me how arbitrary decisions made by the designers of go are thought of as fundamental design rules.
When people use the word “domain model” I know the complex nomenclature has actually led them astray. These are just folders and categories. The term domain model doesn’t change a thing other than making it sound smarter.
Exactly. Like you describe, this domain model has at least two different types of eggs. This matches what was described in the original comment. But, in the original comment, the author was trying to shoehorn all functionality into a single egg type. And, unsurprisingly, it didn't work for him. It wouldn't work in the real world either.
Revisit the model in a way that actually reflects the real world and your circular dependencies are bound to disappear.
Essentially. More likely, without straying too far from the original, you would have something like `animal.Egg` and `food.Egg` (although it is likely that you would want to stray from the original in an actual setting).
You are going to do that type of thing regardless of the language (and especially in languages with more advanced type systems!), even where circular imports and other code structure methodologies are supported. You wouldn't want your `scrambleEgg` function to accept an egg intended to be hatched. The bones are unpleasant.
>You're going to do that type of thing regardless of the language
No I'm not. I'm going to make one Type and it's going to be called EGG. You're going to make an Egg interface and divide it into two subtypes EatableEgg and HatchableEgg.
I don't think you picked up on it but I have one thing, you created 3. And you created 3 just to avoid an orthogonal issue of dependencies. You aren't getting it. In my statement above I was implying that YOU are shoehorning things, NOT me.
Also you have to create a new package now called Types and that's where you put your Egg interface. So go forces you to create a third meta category while other languages I can choose whether I want that or not.
Or I just don't use folders at all in go. Then this issue doesn't even exist. It only exists because I happened to want to use folders, but I can get rid of circular dependencies simply by organizing everything by files.
Enjoy your scrambled bones, then, I guess. But even if you want to model the world as having only one egg type, that type decidedly does not cleanly fit into "animal" or "food", so your taxonomy doesn't work.
> You're going to make an Egg interface and divide it into two subtypes EatableEgg and HatchableEgg.
This seems like a poor assumption. In the real world, if an "EatableEgg" is fertilized into a "HatchableEgg" there will be a type conversion. What was an "EatableEgg" is now a "HatchableEgg" and the "EatableEgg" no longer exists. What do you need the interface for?
> I don't think you picked up on it but I have one thing
Right, but we're talking about types, not things. Things can come in many different types. You even told us a story about how you consider eggs, which are the same thing, to be of different types, so this didn't go unnoticed by you earlier.
> Also you have to create a new package now called Types and that's where you put your Egg interface.
If you were to have a such a thing, wouldn't it go in something like "reproductive structure"? "types" is a strange fit alongside "animal" and "food".
Revisit the model in a way that actually reflects the real world and your circular dependencies are bound to disappear.
>Enjoy your scrambled bones, then, I guess. But even if you want to model the world as having only one egg type, that type decidedly does not cleanly fit into "animal" or "food", so your taxonomy doesn't work.
scrambled bones my ass. There's no instance where that happens. I have a scramble function that takes an egg type as a parameter I don't know where you're pulling the scrambled bones from.
I don't model the world that way, that's not my objective. I live on a farm, I'm just modelling things the way I modelled it on the farm. I organize my eggs into the food box and my hens into the chicken pen. I do this in the real world. I want to do the same thing in my programming and I can't. Understand?
>Right, but we're talking about types, not things. Things can come in many different types. You even told us a story about how you consider eggs, which are the same thing, to be of different types, so this didn't go unnoticed by you earlier.
If you make two different types, and you instantiate those two types you have two different things. I don't think you're getting it. Those two different things cannot represent the real world thing because the real world thing can hatch OR be eaten. The things you created can only do one or the other.
>If you were to have a such a thing, wouldn't it go in something like "reproductive structure"? "types" is a strange fit alongside "animal" and "food".
You have to do this because your Egg interface can't go into animal or food becuase it will cause a circular dependency.
On my farm I don't have a bin or a box (aka type) called reproductive structure or types. I don't need to do this in the real world but I need to do this in go because Go is poorly designed.
Look, I can make a folder called animals and food and I can put anything I want in those folders in other languages. In go, I can't. It's that simple. Go makes this arbitrary restriction out of nowhere and it makes things worse. You're shoehorning new nomenclature and reproductive concepts into your organizational scheme while I can run with what's done in REALITY with significantly less primitives.
>Revisit the model in a way that actually reflects the real world and your circular dependencies are bound to disappear.
I think you're out of touch with the real world. When you type things in the real world (aka putting things into a box or a pen) you don't care about dependencies. I don't put my eggs in the chicken pen because they came from the chickens. I put it in the food pantry. Understand? Folders are designed to do the activity I just mentioned, they are not designed to form some complicated taxonomy of unnecessary concepts.
> I have a scramble function that takes an egg type as a parameter I don't know where you're pulling the scrambled bones from.
Then you're in for an educational treat. Believe it or not, inside a "hatching egg" is a little chicken! And chickens have bones. As your scramble function accepts any type of egg, it may accept an egg that contains said bones.
But it need not be that way. With consideration about your types, you can have the compiler ensure that you only allow "eating eggs" into your scramble function. Just like we normally take care in the real world to ensure the same kind of separation because most people would not be amused if their scrambled eggs contained bones. Apparently you roll the dice, but know that is unusual.
> and you instantiate those two types you have two different things.
I don't disagree, but I don't know of any programming language that has a concept for things. Certainly none that you would actually use for production software. Types are the pinnacle of popular computer science thus far. At some point you are going to have to accept that software and the real world aren't exactly the same.
But revisit the model in a way that actually reflects the real world and your circular dependencies are bound to disappear.
> I organize my eggs into the food box and my hens into the chicken pen.
And the roosters? Those eggs aren't hatching otherwise...
> You have to do this because your Egg interface can't go into animal or food becuase it will cause a circular dependency.
But, most importantly, because it would otherwise be confusing for anyone else who has to work on the code. "Why is a chick about to leave its shell considered food? I don't know anyone who considers that to be food." is the first thing they are going to say upon encountering this codebase.
Code is written for humans. Remember that.
> I put it in the food pantry.
You may put "eating eggs" in the pantry, but I can't imagine you put "hatching eggs" in the pantry. So why are you putting "hatching eggs" in "the food pantry" when taken to the computer? Again, this model you have doesn't even work on a human level, never mind any technical constraints when applied to software.
> Then you're in for an educational treat. Believe it or not, inside a "hatching egg" is a little chicken! And chickens have bones. As your scramble function accepts any type of egg, it may accept an egg that contains said bones.
Except the egg I modeled doesn’t do this and I generally don’t encounter this in the real world so I don’t have to account for it. So your example is meaningless pedantic pointlessness.
> I don't disagree, but I don't know of any programming language that has a concept for things.
The concept of type is a categorization. Instantiating a type is creating a thing that goes in that same category. You’re not getting it because this statement is categorically incorrect.
> Types are the pinnacle of popular computer science thus far. At some point you are going to have to accept that software and the real world aren't exactly the same.
Of course not. The food category and the animal category are not part of the real world. The universe doesn’t categorize things. Categories are made up bullshit by human beings. They aren’t real in any sense. You’re just not seeing this.
What’s going on with golang is that it’s saying your arbitrary categorization of things IS REAL. When you don’t categorize it the go way you actually did something fundamentally wrong is what go tells you. And your issue is, you believe in this go philosophy. You think that what go tells you is real.
Go says a chicken cannot go into the animal category and exist with an egg that goes into a food category. Go says if you try to model things this way something is fundamentally wrong with your understanding of categories and reality and it throws a compiler error to tell you so.
The problem here is that you believe this bullshit. You think golang actually said something profound when really the designer was just an idiot.
> But, most importantly, because it would otherwise be confusing for anyone else who has to work on the code. "Why is a chick about to leave its shell considered food? I don't know anyone who considers that to be food." is the first thing they are going to say upon encountering this codebase.
Code is written for humans. Remember that.
You’re out of touch with humans and you don’t see it. As a human I don’t think about accidentally finding chicken bones in my eggs so I categorize eggs as food and chickens as animals. What’s inhuman and overly pedantic is to consider every possible case and permutation of chickens and eggs and try to model everything in your program. How detailed do you want to go? Everything is made out of atoms so everything belongs in the same category? Be real. You are arbitrarily increasing the resolution of what is encompassed in your model to make some arbitrary and false point about domain modeling.
What you’re not seeing is The model is made up by me to simplify things. In go I can’t make the model simple because I have to model things according to golang.
> You may put "eating eggs" in the pantry, but I can't imagine you put "hatching eggs" in the pantry. So why are you putting "hatching eggs" in "the food pantry" when taken to the computer? Again, this model you have doesn't even work on a human level, never mind any technical constraints when applied to software.
I put eggs in the pantry. I can still hatch those eggs if I want. I can eat them too. You put technical constraints on reality for no other arbitrary reason other then to satisfy gos dependency rules. In your model you restricted your abilities. I changed my mind and I want to use half of my eggs in the pantry for hatching. Your “domain modeling” doesn’t allow for this.
Look this is all arbitrary bullshit. You’re just going to keep making up cases where your model is right but for every case there is also a case where mine is right and yours is wrong. This is because there’s an infinite amount of perspectives to look at this subject. How we choose to look at that subject is an arbitrary choice. You want to make two types of eggs and categorize it that way?be my fucking guest. Most people who farm don’t do it this way but go ahead.
Golang takes this arbitrary choice away. It tells everyone that eggs don’t exist. It’s either a hatching egg or an eatable egg. You live in a universe of golang that tells you that this is the only fundamental way to categorize things: by a dependency tree.
Because we don’t know which came first, the chicken or the egg. In your universe of golang that you live in your saying it’s a fundamental truth that we can therefore never categorize chickens as animals and eggs as food. We must destroy the concept of an egg and realize there are two types of eggs. One that is eatable food and Another that is a hatchable animal.
That’s how your brain sees reality. If this is the case so be it. Can’t be fixed. I can’t change you. More likely you’re just stubborn.
> So your example is meaningless pedantic pointlessness.
Okay, but it is not my example. It was the example given in the very first comment. It what was asserted to have created the circular dependency.
> The concept of type is a categorization.
Okay, sure, but it remains that things are decidedly not categorizations. And, as before, there is no known programming language that has a concept for things. It's an interesting idea! I can see that programming languages could benefit from having such a concept. If you happen to be looking for a CS research project, this just might be it. But if you just want to write production software using existing tools you're not going to find it.
> I can still hatch those eggs if I want.
Your pantry has suitable environmental conditions for incubation, does it? The environment necessary for incubation is not ideal for other foods normally kept in a pantry, so this doesn't really add up. But, hell, let's pretend you do. Do you still not want some way to identify those eggs being incubated and those eggs ready to eat for others, if not yourself, looking into your pantry?
> Golang takes this arbitrary choice away.
Okay, but we're not even talking about Go. We are barely even talking about programming. This model of yours doesn't even fit the real world. Come back with a better model and you won't leave other humans scratching their heads and you might even find the technology won't fight you so hard at the same time.
>Okay, but it is not my example. It was the example given in the very first comment. It what was asserted to have created the circular dependency.
Right and I'm saying I don't like your example. I prefer my example. And any other language is ok with my example except golang. That's my entire point. That's the problem, to get rid of that dependency I have to go with your example and that's bad because I don't have the choice.
>Okay, sure, but it remains that things are decidedly not categorizations. And, as before, there is no known programming language that has a concept for things. It's an interesting idea! I can see that programming languages could benefit from having such a concept. If you happen to be looking for a CS research project, this just might be it. But if you just want to write production software using existing tools you're not going to find it.
You said things don't exist in programming languages and I literally gave you an example of how it does exist. When you use a type to instantiate an object you are creating a Thing. The point of what I said here is that what you said is categorically wrong and you missed it.
>Your pantry has suitable environmental conditions for incubation, does it? The environment necessary for incubation is not ideal for other foods normally kept in a pantry, so this doesn't really add up. But, hell, let's pretend you do. Do you still not want some way to identify those eggs being incubated and those eggs ready to eat for others, if not yourself, looking into your pantry?
Again you're just choosing arbitrary perspectives out of an infinite amount of perspectives. My perspective is another arbitrary perspective. We can model the problem however the way we want at however resolution and detail from talking about incubation in pantries. I can easily just say I can take the egg in the pantry and put it back under the chicken. There. But this is BESIDES the point.
The PROBLEM, again, with golang is that whatever perspective you choose, golang says it has to fit with their rules while the rest of the world and all other languages don't SAY this AT ALL. Other languages give you freedom, go gives you arbitrary restriction.
>Okay, but we're not even talking about Go. We are barely even talking about programming. This model of yours doesn't even fit the real world. Come back with a better model and you won't leave other humans scratching their heads and you might even find the technology won't fight you so hard at the same time.
We are. I think your out of touch with reality. I'm literally talking about what you can't do with golang. You can't simplify the model of the world to my specific model that I originally mentioned because it causes a circular dependency. But you can in other languages.
I'm not fighting technology. The only thing I'm fighting is golang. No other language makes you do this, so it's a problem with golang.
Models are arbitrary choices and they are useful depending on context. For example Newtons laws of motions are actually wrong but they are still useful for modelling things so in a computer program we can still choose to use it. We don't have to use the most "correct" model involving relativity.
The thing with golang is that it's doing something like this. It's saying your model and it's dependencies has to match how I see the universe. You cannot choose the model.
And I don't like road bridges made of concrete and steel, preferring popsicle sticks. But engineering is not driven by feelings, so this is irrelevant.
> When you use a type to instantiate an object you are creating a Thing.
No, like you said earlier, you are creating a classification. The thing being classified isn't expressible. The languages we have are too limited for that. As a workaround we carry an implied assumption that underneath a classification lies a thing, but as you are finding out that quickly breaks down when there is not a clean association between the thing and the classification.
I like what you are thinking, though. I can see how our programming languages could be a lot better if there was such expressibility. But what that looks like is an unsolved computer science problem, I'm afraid.
> We are
No. Definitely not. We touched on it briefly at the beginning, which is perhaps what is confusing you, but we long moved past that to discuss how one might model the world, namely with expression in natural language, but to a lesser extent all programming languages.
> No other language makes you do this, so it's a problem with golang.
English also makes you do this. Failure to will result in an "aktshually, ..." error.
>And I don't like road bridges made of concrete and steel, preferring popsicle sticks. But engineering is not driven by feelings, so this is irrelevant.
The issue is you think I'm saying it has to be made out of popsicle sticks. I'm saying it you can use wood or steel and your saying something along the lines of ONLY use steel. Steel is the only way! That's go.
You're just going off into complete fantasy land thinking that my examples don't work. My examples work. Your examples also work. But my examples are MORE intuitive and simple. Your examples are convoluted and strange.
>No, like you said earlier, you are creating a classification. The thing being classified isn't expressible. The languages we have are too limited for that. As a workaround we carry an implied assumption that underneath a classification lies a thing, but as you are finding out that quickly breaks down when there is not a clean association between the thing and the classification.
When YOU instantiate the class, you are creating a THING. The instantiation is an expression of THAT thing.
Maybe you're referring to a type so narrow that it can only contain One thing? I believe TS has some ability to do this and Idris as well. Basically dependently typed languages allow this.
>I like what you are thinking, though. I can see how our programming languages could be a lot better if there was such expressibility. But what that looks like is an unsolved computer science problem, I'm afraid.
I don't think you have a clue about what you're talking about.
>No. Definitely not. We touched on it briefly at the beginning, which is perhaps what is confusing you, but we long moved past that to discuss how one might model the world, namely with expression in natural language, but to a lesser extent all programming languages.
No you moved on. I stayed on topic. I'm just using models of the world to show you how stupid go is. There are certain models of the world Go can't handle. That's all I'm doing. But I guess the details are getting too complicated for you that you inadverdantly lost track and moved on.
>English also makes you do this. Failure to will result in an "aktshually, ..." error.
Is this supposed to be a joke? English supports circular dependencies. Your equivalent of an error in english is a grammar error. Circular dependencies don't trigger a grammar error.
If you're trying to make a joke it's not even funny.
This bothers me from time to time. When I first started using Go, I think I complained to the Go team about it. They told me to think more carefully about where package boundaries are. Having the smallest package possible doesn't necessarily mean the design is good.
I inherited an app from a coworker, and he just put every file in the main package. This was actually fine and caused no problems.
These days, I still have an addiction to making tiny packages, which the Go team would likely not approve. But I'm a big girl and I do what I want! The workarounds I use are:
1) A `types` package. type Chicken struct { Children []Egg }; type Egg struct { Mom, Dad Chicken }.
2) A `utils` package. Let me explain. I would never name a package `utils`. That's illegal and I'm told that the compiler will explode into a thousand pieces if you try. All the king's horses and all the king's men wouldn't be able to put it back together again. So don't test it. Just trust me. But, you can definitely have something like `package hatchery` with a functions related to collecting eggs from chickens. Or you can have `package eggutil` for packing eggs, frying eggs, and shipping eggs.
I would say that I typically have a `types` package (called `types` if I'm hand-writing the code, or myapppb if it's protobufs like at Google), and then structure the rest of my app as model/view/controller. The model puts these types into the database. (Call it `eggdb`.) The controller does whatever business logic you care about (getting chickens together to fertilize eggs, call it `husbandry`). The view calls into the controller to implement your API / gRPC endpoint / beautiful Gtk+ GUI / whatever.
And then you don't really have problems with circular dependencies.
Having said all that if someone puts it all in main.go I'd probably approve the PR. The Go team let my coworker do it in 2014 and nobody died.
You’re not seeing the problem. You spend an inordinate amount of time trying to organize it and you come up with an elegant way so the catharsis of that solution makes you think you found the path to nirvana. Really you’ve been duped.
This restriction makes sense for packages. But not for folders. The problem arises in go because folders and packages are the same thing and that’s stupid because people don’t typically use folders as if they were packages. Folders are typically used just to categorize things of similar meaning or naming or whatever you want.
No other popular language has this issue. I can choose to organize things how I want in any other language. I have the freedom. I can make a folder A and B and C and D and just organize things in ABC order. But can’t with go. If I dont want to do this in any other language I have the option to create a package.
Creating a package and creating a folder are completely orthogonal tools and concepts and the genius who invented go just made a horrible design decision here.
> that’s stupid because people don’t typically use folders as if they were packages. Folders are typically used just to categorize things of similar meaning or naming or whatever you want
You might do that. That does not mean everyone organizes things like this.
What your chicken/egg example fails to realize is that things rarely just belong in one category. Chickens can be animals or food.
To me it just sounds like you are trying to write another language while using Go. Of course you will see problems. Just as you would see problems trying to write Go code when using Java.
In the end it comes down to this: if the language does not fit your mental model on how to do things, don't use it. But don't go around shitting on the language just because you are used to using folders differently than other people. Using a language also means learning and using the conventions of that language.
>You might do that. That does not mean everyone organizes things like this.
Most people do organize things arbitrarily based off of their own categorizations and opinions. In fact such an overwhelming majority of people who use operating systems do this that it's pretty much universal.
>What your chicken/egg example fails to realize is that things rarely just belong in one category. Chickens can be animals or food.
So what. I choose not to eat my chickens. So I Choose to categorize it in a way that makes sense to me. Why should I conform to your point of view? Why should I conform to golangs point of view? Why can't you and I choose how to do it?
>To me it just sounds like you are trying to write another language while using Go. Of course you will see problems. Just as you would see problems trying to write Go code when using Java.
No. I'm complaining about go. I think it's dumb. I'm not doing OOP here, I hate OOP. Go is waaay better. This is orthogonal to that problem.
>In the end it comes down to this: if the language does not fit your mental model on how to do things, don't use it. But don't go around shitting on the language just because you are used to using folders differently than other people. Using a language also means learning and using the conventions of that language.
Yeah that's how all complaints and criticisms are sidelined. "You don't like it, don't use it. Use something you like." Obviously.
I'm doing exactly that, while saying that go packages are a poor and horrible design decision.
I think a lot of people hated java, and found go and they think because go is so much better then java then that means go can do no wrong.
I don't think you realize there's stuff way better then go out there. But that's besides my point. What I use is separate from my point: Golang packages are poorly designed.
> I don't think you realize there's stuff way better then go out there.
Every language makes trade-offs. For you the trade-off Go makes is bad. I disagree. I like some languages better in certain parts, while I prefer Go's solution in other parts. It's all preference, there is almost never an objective "better" or "worse" like you seem to think.
Then you disagree with the majority of people. That's my point. This agree/disagree side lines the fact that people can be right or wrong. My claim is not only do you disagree, but you're wrong.
Majority of what people? Get off your high horse, your opinion is not a fact. Give me objective metrics to measure how "good" a language or language feature is, otherwise you are just wrong.
I'm looking forward to trying out your own perfect language that is objectively the best for any use case ever and no one can find any faults with it. Because surely such a language exists.
>Majority of what people? Get off your high horse, your opinion is not a fact.
Just look at reality and how people organize things everywhere. It's arbitrary. Adults are placed in offices and kids are placed in schools. Then on family trees kids and Adults are organized by dependency. How people organize things in the REAL world is AN arbitrary choice. But in GO you have NO CHOICE. It has to be by family tree. That is NOT an opinion. Everything I said is FACT.
The metric is basically the entire world and everything in it and how we fundamentally type (aka organize) things within it. But if you want to get more specific just look at every other programming language except go and look at how the entire world uses folders in operating systems. These are tools to allow people to arbitrarily organize things.
>I'm looking forward to trying out your own perfect language that is objectively the best for any use case ever and no one can find any faults with it. Because surely such a language exists.
Don't have one. I'm just commenting on what I hate about golang.
So a hand-wavy "look at the world bro" instead of actual metrics. Got it.
> I'm just commenting on what I hate about golang.
No you're not. You say Go (or a part of Go) is bad, which is vastly different. If you stuck to "I don't like it", you would not have gotten so much push back, but you insist in being right and everyone else is stupid and wrong.
Because metrics don’t exist. If the only way you can move forward and know something is because someone conducted some sort of statistical experiment with data analysis on it then I don’t even know how you get up in the morning. Do you need science to prove that when you jump off the bed there’s a floor that your feet will land on?
No you don’t. You’re not an idiot. It’s common sense that allows you to do this and it’s common sense that will allow you to see that the entire world works the way I said it does above. You don’t need science for this. At least most people don’t. Maybe you’re different and you need science to do an analysis for you before you open any door to make sure reality still exists behind it.
> No you're not. You say Go (or a part of Go) is bad, which is vastly different. If you stuck to "I don't like it", you would not have gotten so much push back, but you insist in being right and everyone else is stupid and wrong.
You’re right. Let me rephrase what I meant. I’m commenting about what is fundamentally terrible about golang and if you disagree then you're wrong because the overwhelming majority of the world would disagree.
> You spend an inordinate amount of time trying to organize it
I mean, I don't. I've been doing Go for well over 10 years, so I'm well aware of the limitation and intentionally avoid running into it. "Well I hate that!" Yeah, we know. What can you do about it? Use something else.
In a past life, I taught Perl classes at companies that use Perl. One time I was explaining the advanced parts of @INC (the module lookup configuration/resolution order variable). One student hated it to the point of tears. They could not live with a programming language that had an @INC variable. Nothing I can do about that. It does. Get over it, or don't get over it. Those are the only two options.
This is solved simply by having a chicken.go and an egg.go in the same package.
Go appears to encourage large source files, since it allows you to define multiple "classes" (types with methods) within the same file. This is probably intentional to combat the complexity of having otherwise cohesive logic littered across several small files in OOP-first languages.
But I like your example and get your point. What if chicken.go and egg.go diverged a few levels earlier in the dir path. All the Go repos that I've seen in production have very flat folder structures, so I guess this is just how Go is written.
I joined a company who wanted really clean code in their code base. That meant really good categorical organization of things into folders based off of semantic meaning about what those primitives did. You can imagine the nightmare that caused.
People simply just didn't understand what I was saying that there was no inherent meaning in trying to make our naming conventions with folders work with go's dependency rules. They thought the work of untangling all the dependencies, folders and the naming was some quest towards a perfect design.
You can also see in this thread, that a lot of people debating the issue with me believe the same thing. They think this arbitrary rule is speaking to a fundamental design axiom and they use big words to call it "domain modelling"
For me it starts with allowing only source code packages, followed by direct URLs to source code repos directly on the source files, instead of an indirect mechanism.
To be fair, Go modules provide such indirect mechanism, by rewriting source files, with redirection information, really? Yet another hack.
If you have two files in go or any other language, circular dependencies are usually permitted which also makes sense. It’s only packages that don’t permit this.
But guess what? You create a package in go simply by putting everything in a folder. So people when writing a go project they often make dozens of packages just by the is ocd need of organizing things into folders.
But when you organize things into folders the files in those folders aren’t project files anymore. They are different packages and you can’t have circular dependencies.
And that’s a big problem as this design conflicts with programmer instincts on how to organize things.
We organize things by meaning and name and subject matter. But simply using folders in go we are forced to organize things via dependencies and this causes a clash and makes organizing things 10 times harder than it should be in go.
Imagine I have a chicken and an egg. Chicken goes in the animal package and egg goes in the food package. It is now fundamentally impossible to make a chicken lay an egg and an egg hatch a chicken at the same time. Our tendencies to organize things via meaning has clashed with this requirement of organizing things via dependencies.
Does it make any sense at all? We probably don’t want packages to be interdependent in this way. But the stupid thing is just be creating a freaking folder we create this problem in go and it doesn’t make sense because if the files are outside of a folder you don’t hit this problem.
I would say go is actually poorly designed. I can’t think of any popular language that has this strange inconsistent problem.
It actually causes huge headaches in organizing things in go but idiot developers when they hit this circular dependency problem they literally believe the documentation when it tells them that they aren’t organizing things correctly and they need to think harder about design. So in a lot of go shops they spend an inordinate amount of time naming folders and organizing shit just to get their ocd need of organizing things by name to jive with gos requirement to organize things by dependency.
In the real world things can be in different categories and also interdependent at the same time. Go’s universe doesn’t allow this.
I’m here to tell you that It does make sense to put eggs in the food folder and chickens in the animal folder. Go is just stupid in this area, not you. Don’t believe the idiot who wrote that in the docs.