Pretty much any null pointer deference error ever?
But it is hardly ever the weak type system that is at fault, just good use of a stronger type system could have prevented the issue.
Once you start to make "invalid states unpresentable" and enforcing those states at the edges of your type system suddenly a lot of bizarre errors don't happen anymore.
What people usually do is add a build tag to the file(s) with package main, so they're not compiled on a regular compile/test run. But you can't combine them as such (and you can do this with any package name – there's nothing special about the main package here).
No, there is no exception for the "main" package. It's just build tag trickery. You can do this with any package names (although it doesn't make much sense to do so).
> contrasting craftsmanship and utility, since both are somewhat prized on HN
I'd say they're prized everywhere, though "craftsmanship" is really subjective. and the HN I usually [edit/add: see] seems to have more a meta of "criticize anything someone tries to build, and rave about IQ" tbh ;)
SQLite works and I don't have to think about it why it works (too much). That is IMO a true hallmark of solid engineering.
I was recently having a conversation with some coworkers about this.
IMO a lot of (software) engineering wisdom and best practices fails in the face of business requirements and logic. In hard engineering you can push back a lot harder because it's more permanent and lives are more often on the line, but with software, it's harder to do so.
I truly believe the constraints of fast moving business and inane, non sensical requests for short term gains (to keep your product going) make it nearly impossible to do proper software engineering, and actually require these if-else nests to work properly. So much so that I think we should distinguish between software engineering and product engineering.
> a lot of (software) engineering wisdom and best practices fails in the face of business requirements
They fail on reality. A lot of those "best" practices assume, that someone understands the problem and knows what needs to be built. But that's never true. Building software is always an evolutionary process, it needs to change until it's right.
Try to build an side project, that doesn't accept any external requirements, just your ideas. You will see that even your own ideas and requirements shift over time, a year (or two) later your original assumptions won't be correct anymore.
You can still design for evolution and follow best practices. That's actually IMO a hallmark of good software design.
The issue is when the evolution is random and rife with special cases and rules that cannot be generalized... the unknown unknowns of reality, as you say.
This is how I feel as well. What's even worse is that it seems like the academics doing research in the area of software engineering don't really have up to date experience that's practical.
Add to the fact that they're the professor of many software engineering courses and you start to see why so many new grads follow SOLID so dogmatically, which leads to codebases quickly decaying.
every language has its problems; Go I think is pretty good despite them. not saying points raised in the article are invalid, you def have to be careful, and I hate the "nil interface is not necessarily nil" issue as much as anyone.
It's hard to find a language that will satisfy everyone's needs. Go I find better for smaller, focused applications/utilities... can definitely see how it would cause problems at an "enterprise" level codebase.