Hacker News new | past | comments | ask | show | jobs | submit login

I'm in the same position as OP and was wondering the same thing; finding a job using Go. Is the bloat that you see the most related to error checking? If not what else is it?



The bloat is mostly related to mocking and making a fake client for everything for unit tests, and the practices you have to follow to make that actually work.

In Python or Java, you can do something like:

class: f1(): self.some_api_call() <process api call here>

test_class extends class some_api_call(): <mock definition>

In go, you cannot do this. Fair enough, but everyone writes object-style code because it's easier and there's less boiler plate. If you do this, you can't write tests.

Instead, you have to do something like:

class: apiMethod = nil f1(): self.apiMethod() <process api call>

And assign apiMethod when you create the instance of the object; there are no constructors because they're not traditional objects, you need to create a factor method (boiler plate) or build the struct by hand (boiler plate). None of this is terribly challenging in and of itself, but if you work on large code bases, nobody did this because it's extra work, and now you have to refactor it because you want to make a change to the critical business logic and prove you're not introducing a regression (a constraint the l33t coders before you didn't have because they get to go fast and break things).

And finally, often times the thing you need to mock is in someone else's package, and it doesn't implement an interface, or the thing you need to mutate is private, etc, etc. You end up need to mock half of a package sometimes.

None of this is insurmountable, but when you do it day in and day out for years like I did, it's a real slog, and it sucks your soul out of your body. It wasn't uncommon for me to spend literally 20x as long refactoring and implementing tests as it was to ship features. If you look at some unit tests from large go projects, you'll see stuff like struct{struct{struct{struct{...}}},struct{struct{struct{...}}}} because so much stuff needs to be mocked up. And since interfaces are disjointed from classes, you won't know with certainty which methods you need to needlessly mock for your mock class until you try to compile, because the interface is defined somewhere else and not attached to a base class, it's just a definition floating out there in the source somewhere.


I'm reposting your message with the code formatted as you had entered it (the original white space use is still visible in the html source code; I've just indented it so that HN recognizes it as preformatted):

---

The bloat is mostly related to mocking and making a fake client for everything for unit tests, and the practices you have to follow to make that actually work.

In Python or Java, you can do something like:

    class:
      f1():
        self.some_api_call()
        <process api call here>

    test_class extends class
      some_api_call():
        <mock definition>
In go, you cannot do this. Fair enough, but everyone writes object-style code because it's easier and there's less boiler plate. If you do this, you can't write tests.

Instead, you have to do something like:

    class:
      apiMethod = nil
      f1():
        self.apiMethod()
        <process api call>
And assign apiMethod when you create the instance of the object; there are no constructors because they're not traditional objects, you need to create a factor method (boiler plate) or build the struct by hand (boiler plate). None of this is terribly challenging in and of itself, but if you work on large code bases, nobody did this because it's extra work, and now you have to refactor it because you want to make a change to the critical business logic and prove you're not introducing a regression (a constraint the l33t coders before you didn't have because they get to go fast and break things).

And finally, often times the thing you need to mock is in someone else's package, and it doesn't implement an interface, or the thing you need to mutate is private, etc, etc. You end up need to mock half of a package sometimes.

None of this is insurmountable, but when you do it day in and day out for years like I did, it's a real slog, and it sucks your soul out of your body. It wasn't uncommon for me to spend literally 20x as long refactoring and implementing tests as it was to ship features. If you look at some unit tests from large go projects, you'll see stuff like struct{struct{struct{struct{...}}}, struct{struct{struct{...}}}} because so much stuff needs to be mocked up. And since interfaces are disjointed from classes, you won't know with certainty which methods you need to needlessly mock for your mock class until you try to compile, because the interface is defined somewhere else and not attached to a base class, it's just a definition floating out there in the source somewhere.


for me it's lack of map/reduce




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: