Hacker News new | ask | show | jobs
by david-cako 2154 days ago
It's really hard to point at studies to evaluate these types of hyped development paradigms. Some thoughts, as someone who loves static typing and microservices:

My favorite thing about static typing is that it makes code more self-documenting. The reason I love Go specifically is because if you have 10 people write the same thing in Go, it's all going to come out relatively similar and use mostly built-in packages. Any API requests are going to be self-documenting, because you have to write a struct to decode them into. Any function has clear inputs and outputs; I can hover a parameter in my IDE and know exactly what's going on. You can't just throw errors away; you always are aware of them, and any functions you write should bubble them up.

Typescript addresses this somewhat, but basically offsets that complexity with more configuration files. I like Typescript in use, but I can't stand the fact that Javascript requires configuration files, transpilers, a million dependencies. Same for Python and mypy.

Yes, I could just look at class members in a dynamic language, but there's nothing that formally verifies the shape of data. It's much more annoying to piece apart. I don't use static analyzers, but my guess is that languages like Go and Rust are the most compatible with them. Go programs are the closest thing to a declarative solution to a software problem, of any modern language IMO. As we continue experimenting with GPT-generated programs, I think we're going to see much more success with opinionated languages that have fewer features and more consistency in how finished programs look.

Microservices are also great at making large applications more maintainable, but add additional devops complexity. It's harder to keep track of what's running where and requires some sort of centralized logging for requests and runtime.

1 comments

You certainly can throw errors away in Go -- in various ways. It's one of the notable flaws in a largely cohesive, sensible language. (Which I use daily.)

    success, err := fail()
    do(success)

    success, _ := fail()

    fail()
I suppose my point, more specifically, is that functions return errors instead of opaquely throwing them. Most languages expect you to know where they're going to occur and catch them as close to their occurrence as possible, in Go you are explicitly carrying them along the whole way. Some people don't like this, I prefer it.

True, if you completely ignore the function's return values, you can throw errors away, but then you wouldn't be using the language in the way that makes it powerful to me; that there are simple and clear interfaces that you interact with.

The second one is pretty intentional - it'd be annoying it were downright impossible.

The first and third one fails on go vet. The first one also fails to compile if you never read from err in the entire function.

Vet accepts the third, and may (I forget) accept the first if err is redeclared or simply assigned.
My bad, I was thinking of errcheck, which is more thorough and integrated into most Go linting tools like Go CI linter.

https://github.com/kisielk/errcheck

In any case, it’s trivial to detect via static analysis.