HNHacker News
TopNewBestAskShowJobs

natefinch

2,096 karma · joined September 12, 2012

Software Engineer since 1999 in the Boston area. natefinch on github https://npf.io

[ my public key: https://keybase.io/natefinch; my proof: https://keybase.io/natefinch/sigs/zmM0s7UYyYw1F1gFUV2w0MZmAdRu5w1R0AMnw-7wWQg ]

submissionscomments
natefinch··on Cost of owning a BMW i3
I mean, you can get a Tesla Model 3 long range for $47k that goes 310 miles on a charge and gains 200 miles on a half hour recharge at a supercharger. That seems... like more driving than I'd really ever do. (half hour is super easy to blow when you go pee, grab a coffee, check your email and social media... and keep in mind that's after like 4 hours of driving)
natefinch··on Declined Proposal: A built-in Go error check function, “try”
I really dislike method chaining. I'd much rather have 5 lines than 5 chained methods. If that's too much to read, you can always encapsulate it in a well-named function.
natefinch··on Declined Proposal: A built-in Go error check function, “try”
Try makes it worse because it is so easy to miss when reading the code. Because it encourages nesting function calls, which is harder for a human to parse than separate statements across lines. Because it means you can exit the current function from the middle of a line of code, and what runs before or doesn't run before is based on order of operations rather than requiring the exit to be a statement on its own line whose order cannot be misunderstood. Because it discourages giving more information with an error, so instead of "failed to open config file: EOF", you just get the EOF.

Go's error handling isn't any more error prone that writing if statements for all the rest of your code. if err != nil is no different than if age < 18. Either one is a branch in the code. I can literally count on one hand the number of times in 6 years of full time go development that I've seen people miss writing the if err != nil.

Being explicit is good. Spreading out the logic is good. Cramming a lot of logic into one line is bad.... and that's the sole purpose of try.

Maybe there's another way to make error handling better in Go. I'm not averse to looking into that. But try wasn't it.

You're talking about writing if err != nil being tedious, but what about matching Results from Rust, isn't that tedious? What about writing proper catch blocks in java or C++ or python, isn't that tedious? It's all just logic.

natefinch··on Declined Proposal: A built-in Go error check function, “try”
Literally the first non-trivial code I wrote in go (running a bunch of goroutines to download a ton of files from a website in parallel)... I knew exactly where and how things could fail and where things were failing just by looking at the code. Coming from C++ and C# and Python, there was no comparison. I had never been so confident in the code I'd written, even though I was a newbie at Go and a veteran of the other languages.
natefinch··on Go Creeping In
Functions are a thing. Interfaces are a thing. I have literally never, in 6 years of full time go development, just copied and pasted code for the purpose of making it work with a different type. Nor has anyone I have worked with in that time (to my knowledge). I have seen two or three libraries written that use interface{}, but these are by far the exception.
natefinch··on Go Creeping In
I've worked on a million line Go code base and a dozen open source projects and many typical backend services, and interface{} is actually quite rare outside of something like json serialization or string printing - i.e. fmt.Printf(msg string, args ...interface{})

I almost never see code that application developers write using it, and usually if someone is writing that code, it's wrong, and I help them figure out how to avoid it.

Usually you can avoid it by using closures or interfaces.

natefinch··on Error Handling in Go (2016)
I've been writing Go for over 6 years. Error handling at the source of failure is a feature, not a bug.

Rob Pike's example code is bad and I would not allow it through a code review. Why? It makes the code lie. It appears as though the writes cannot fail, but in fact they can, and later writes become no-ops. On top of that, it means that you lose the context of which write failed. Did you fail writing the header, the body, or the footer? You can't know anymore.

This is like

   try {
        doThing()
        doThing2()
        doThing3()
   catch (Exception ex) {
      // handle
   }
You can't tell what failed. You can't tell what is possible to fail. The handler can't differentiate.
natefinch··on On Learning Rust and Go: Migrating Away from Python
C++ versions are never correct
natefinch··on Toml: Tom's Obvious, Minimal Language
IF you have a 500k LOC software project... how the heck is an SRE/devops person going to figure out where in that code a specific configuration item is going to be used? They're not. This is why documentation is essential for projects. You could keep configuration documentation in a separate file... but that only helps for what the config does. It can't help you figure out why Bill (who left the company a while back) set ThreadMax to 650 when he changed the code 6 months ago. There cold be a commit message that references it, but that's more disconnected from the change that just slapping a comment on top that says why.

I agree that code review for configuration changes is necessary. That same code review process can ensure that the comments in the config file are also correct.

natefinch··on Toml: Tom's Obvious, Minimal Language
Hugely disagree. Config files will modified by non-experts of the application 1000x as often as the actual developer of the application. Those people won't and often can't go look at the code.

Also, it can be really hard to find where exactly a configuration value is used. You may have to trace through a ton of code to find the place, and then you can't be sure that's the only place it's used.

Configuration comments are crucial, both for onboarding new users (explaining what the default is if you don't set a value, explaining what the configuration value actually controls, etc) and for experienced users to tell others why this esoteric configuration is set the way it is.

A configuration file is literally just a stack of magic numbers and strings. Why are we setting threadpool to 10 and not 1000? Why are we disabling X feature? What the heck does TPS_Report=true do?

You need comments.

natefinch··on Error handling in Upspin
hell no. Rule #1 - users should never see stack traces. Every time some python tool fails and dumps a stack trace, I want to throw my computer across the room. As as user, I never want to see a stack trace. I have zero interest in debugging some random tool. Show me a decent error message with tips on how to get more info. If you want a stack trace that I can give in an error report, put it in a log file somewhere.
natefinch··on Modern terminal-based text editor
Have you tried micro? It has basically all of that.
natefinch··on Why Slack is inappropriate for open source communications
That puts the onus on every single person to maintain the history of the project. Lots of people delete mail (not me, but lots of people). Also, you can't retain history of what was sent before you joined. Also, emailing individual documents means people can't research by themselves.
natefinch··on Why Slack is inappropriate for open source communications
No, email is terrible. There's no history. You can't "scroll up" to see what people were talking about. You can't link to another specific email to reference it (yes, there's archive services, but then you have to go dig through an archive to try to find a horridly formatted email to link to, which is completely separate from the normal consumption platform).
natefinch··on Ask HN: How do I deal with the first sexual harassment complaint at my startup?
If you don't know by 21 that calling a woman a milf is degrading and offensive, you're never going to learn. Or at least not in any timeframe where it's valid for this company.
natefinch··on For Better or for Worse
Not so bad. And the one I'm working on in Go is definitely helped by being in a simpler language. I don't really think immutable data would be a huge boon to maintainability. Some sure, but I think it would also complicate some of the code.
natefinch··on For Better or for Worse
All of the most popular languages have mutable data by default. 99.99% of all enormous systems were written with mutable by default languages.

The type system not being "strong" simply means that you put logic in functions and methods instead of magic parts of the type system.

And Go can absolutely make abstractions. The standard library is full of abstractions. Every Go package is an abstraction. Hell, every function is an abstraction.

natefinch··on For Better or for Worse
The Go language is an excellent tool for shipping maintainable server-side applications.
natefinch··on For Better or for Worse
The Google name surely gets a lot of people's attention. But if the language actually sucked, it's not going to matter. This is a tool that you have to use EVERY DAY. The Google name is far from a guaranteed hit maker. See Google Plus, Google Wave, etc.

That's like saying Dale Earnhardt could recommend driving a Gremlin... sure, it would get a lot of people to go for a test drive, and a lot of those people would then run away.

I fully admit I clinked on the link to the Go website purely because it was from a big name... the exact same thing I did for Hack and Swift and Rust. But I don't write code in Hack or Swift or Rust. I write code in Go.

Sure, I may have missed some really great language put out by an obscure name that never made it to Hacker News. But then again, evidently so did everyone else.

So why do I write code in Go? Because the language and the ecosystem around it are really good. Because I feel like I can understand any piece of code written in it without needing a PhD from Stanford. Because I feel like it pushes people towards simple, straightforward solutions.

Past that first click, the only thing Google means to me is a guaranteed check to pay the bills of all the great people working on the project.

natefinch··on Q&As with Leading Remote Companies
FWIW, I work for Canonical, which is also all remote work, and I got a reasonably big pay bump compared to my last job at an office. Yes, of course someone in Argentina is going to get paid differently than someone in New York City. I don't know how it works at other companies, but at Canonical, you're paid a competitive salary for companies in your area. So, for me, that means companies in the Boston area. I certainly didn't take a pay cut to work remotely. Obviously, what you get paid is different from company to company, but I doubt many companies would be successful in hiring quality engineers if they didn't pay as well as office jobs. Remote work is definitely a big plus, but at the end of the day, it doesn't pay the bills (it does save some money though - I don't need to get a $250 monthly train pass or pay gas/parking etc).
natefinch··on Go 1.4 is released
Cramming a lot of logic into a single line of code is an anti-pattern and not a goal of the go language.

Also see the aforementioned "the answer is to write a loop".

natefinch··on Go 1.4 is released
Most of the questions about "how do I do X in Go?" are answered with "just write a loop". Yes, that means map/reduce, filter, fold, zip, etc. If writing simple loops gets your hackles up, Go is not the language for you. For me, I worry about the hard stuff, not easy loops.
natefinch··on Go 1.4 is released
This is why Go has standalone functions and interfaces. You can easily share logic between types without having the types be the same thing.

The biggest problem with inheritance is that it's a lot like monkey patching (except in production)... the rest of the base class's code expects method X to do ABC, and you've just swapped out the implementation to do LMNO ... and if that never bites you in the ass, you're luckier than most OO programmers I know.

natefinch··on The Case for Slow Programming
There's no required package manager. By default, your VCS is your package manager. You can write code for a long long time with just the default go tool. Those are optional tools that you can use once you become comfortable with the language and understand their tradeoffs. You really don't need any of those tools until you want to write a professional project with multiple people on a team.
natefinch··on Go is moving to GitHub
The git CLI is a mess. It's inconsistent even within its own commands. For example, sometimes specifying remote and branch is done as "remote/branch" and sometimes as "remote branch".

It even uses different words for the same thing - sometimes remove, sometimes rm sometimes -d.

Common actions often require obscure command lines, like "make a new branch" which is git checkout -b instead of just "git branch".

The reason people don't use other git frontends is that a vast majority of the help topics already out there only reference git itself. So if you want help for rebase, for example, if you're using some frontend that re-kajiggers the command line, all that help is now useless, or even worse, potentially downright incorrect.

natefinch··on Why Go is elegant and makes my code elegant
For one thing, it's just a simpler language. There are fewer keywords, there's only one kind of pointer (and no pointer arithmetic). Everything is just pass by value. There's very rarely anything going on "behind the scenes". The code does what it says it does. There aren't any dense one liners that do a whole bunch of stuff. Values are very easy to reason about. You know exactly how values will be initialized, how much memory they take to copy, when they'll be copied.

There's no operator overloading, macros, or monkey patching, so you don't have to know about the entire state of the universe to know what one little function will do. There's no destructors or finalizers that magically get called sometime in the future.

There's no exceptions, so you never have to worry that the control flow of your program is going to jump all over the place. There's multiple returns, so you almost never have null pointer exceptions, because you always just check the error before using the value returned.

And of course, channels and goroutines make modern multithreaded code very easy to reason about, because they're just functions and a little pipe primitive. They don't do a lot of fancy schmancy stuff, and that's good. It means it's very easy to tell what go Foo() will do.

There's probably more I can't think of right now.

natefinch··on Why Go is elegant and makes my code elegant
One of Go's major features is that any particular function is very easy to reason about. The code is very straightforward, there's very little magic, and the code usually does exactly what you expect it to do, even if you're not an expert in the language.

Rust seems nice, but its multitude of different pointers and mutable versus non-mutable data really makes for complicated code.

I work on Juju. It's over 200k lines of code spanning several applications that coordinate across multiple machines. The number of times generics would have helped the codebase I can count on a single hand... and none of it is huge stuff, just some very minor parts of the code.

natefinch··on What happens when you give 4chan images of the Boston Marathon?
I have a laptop backpack like that. On Monday it was 27ºF at 6:30am when I left for work, but it was supposed to be 55-ish during the day. So, I wore a light jacket under my warmer jacket. My work laptop is a 15" Dell and is somewhat heavy.

When I was going home, I stuffed my lighter jacket in my backpack with my laptop... and it looked exactly like that. In crowded areas, when I'm not going anywhere, I almost always take off my backpack and put it between my legs. It's the only way I can safely swivel my upper body to look around without knocking people over.

Don't jump to conclusions. It's a dude with a big black backpack. There's hundreds of thousands of those in Boston. I would be surprised if there weren't a picture of a guy with a big black backpack in that area. Lots of people work around there and lots of people don't get the day off... I didn't. I saw a ton of regulars on the Commuter Rail that morning that obviously also didn't get the day off.

I applaud the efforts of people to scan photos looking for the perpetrators... but saying they may have found the guys responsible is incendiary and dangerous.

natefinch··on Mind-Blowing Facts That Will Make You Use Email Again
Advertisement submitted by a newbie, first comment is by a newbie, 10 bucks says all up votes are from newbies.
natefinch··on Gotchas, Irritants and Warts in Go Web Development
Honestly, my guess is that you were doing something wrong in the Go code. Go is definitely faster than Ruby, even on a single core machine. http://benchmarksgame.alioth.debian.org/u64/benchmark.php?te...
← PreviousPage 2 of 3Next →