12 ms·
Warming up to Go
- bluejekyll 11y agoBut the expense of extra lines of coke come at significant maintenance costs. It means needing more test and the inevitable bugs that will be discovered. More lines of code is inherently a bad thing, while I'm all for simplifying the code so that people can understand it, I'm not a fan of doing that at the cost of increasing the amount of maintenance that will be needed on the code base overtime.
- actsasbuffoon 11y ago> But the expense of extra lines of coke come at significant maintenance costs. That is the single greatest typo I have ever read.
- notNow 11y agoCode is coke at least this is true for some hardcore people here.
- FilterSweep 11y agoAnd its wonderful to see. I'm humbled a̶l̶m̶o̶s̶t̶ every time I read HN.
- to3m 11y agoAlso in the running, this priceless slip: https://news.ycombinator.com/item?id=3726842 https://news.ycombinator.com/item?id=3726842
- z92 11y agoLooks like that one was later corrected. Wondering what the mistake was originally.
- pbnjay 11y agoIf you need more tests to cover the "extra lines of code" resulting from the explicit nature if Go code, then your prior tests didn't sufficiently cover all the edge cases. So Go's verbosity is a win.
- PuerkitoBio 11y ago> But the expense of extra lines of co[d]e come at significant maintenance costs. All lines are not created equal. if err != nil { return err } Those 3 lines have very, very little maintenance cost. The obvious must also be mentioned: less lines of code usually mean building on abstractions - the lines of code are in there, somewhere, but not in your code. Better hope that abstraction is well-tested. Of course it's all a matter of balance, but I disagree with "more lines of code is inherently a bad thing", which stated another way, would mean "cram as much information as possible in a single line of code". In the end, lines of code are a bad metric of software.
- saurik 11y agoLess than other lines, but I definitely would disagree with the doubled-up "very" on "little". In addition to simply being distracting and verbose, a core issue is that you have to make certain you always have the boilerplate and that you have to make certain it is always correct. Otherwise you just https://gotofail.com/ https://gotofail.com/ :(.
- jacques_chester 11y ago> Those 3 lines have very, very little maintenance cost. These three lines are everywhere, give me no clear indication of whether they are intentional behaviour or merely a boilerplate-by-convention, and worst of all, they obscure the actual business logic.
- PuerkitoBio 11y agoError handling does not obscure the business logic, it is very much part of the business logic.
- jacques_chester 11y agoIf your business is handling full disks and HTTP timeouts, sure, exceptions and business logic are the same.
- bkeroack 11y agoGo is a little more verbose in basically two ways: it forces you to handle error states explicitly, and it doesn't let you do overly-clever things to save a few lines of typing. Neither of which increase the maintenance or testing burden.
- jacques_chester 11y ago> it forces you to handle error states explicitly, Does it? `if err != nil` is a convention. It's not a checked error. It's like saying "C has explicit array bounds checking", if the convention was to check it by hand. For all the hate Java gets, when I have a checked exception, I know what it is going to be. I don't need to dig around in sourcecode trying to work out if I should care or not. I don't need to check which of the three Golang error-distinction idioms (package-variable errors, error subtypes, plain-old-errors-with-magical-strings) is in play. As you can guess, I don't like Go.
- sagichmal 11y ago> `if err != nil` is a convention. It's not a checked error. It's... obviously both.
- jacques_chester 11y agoSorry, typo. "Checked exception", meaning that the compiler enforces error handling and that you can look a method signature and learn what kind of exceptions the method can throw without needing to read its internals.
- fooster 11y agoAnd runtime exceptions? What about them?
- jacques_chester 11y agoThey leave you in about the same position as a programmer in a dynamic language. The advantage of runtime exceptions over Go is that I will get a fatal crash and a stacktrace. I don't have computation proceeding in an undefined, difficult-to-debug way because I forgot to do `err != nil` somewhere (particularly for functions that only return err).
- clamprecht 11y ago> But the expense of extra lines of coke Please tell me that was autocorrect and not muscle memory
- erkose 11y agoYikes! Understanding the code is the key to efficient maintenance.
- struct 11y agoI've found that there are only two reasons I like Go: 1) It's concurrency model was a revelation compared to anything I did in the C world. 2) It's opinionated. Everything else is a bonus. In Go, there's only one way to format your program correctly, there's only one way to document your program correctly, there's only one recommended way to serialize to JSON, it only has one (IMO really awesome package management system) etc. It's remarkable how little thought I now need to put into those things.
- threeseed 11y agoEvery programming language starts out like that though. It's just that over time needs/requirements change and then suddenly you have another package manager, another JSON parsing library etc.
- generic_user 11y agoAs a counter argument I would point to C, C++ and Lua as examples of languages that try to keep a basic generic standard library and let everything else fall out in third party libraries. I consider Go more in line with the C family then with the scripting languages like Python etc, With a slightly bigger stdlib.
- iofj 11y agoI disagree strongly. You should keep into account that Go is a very young language, and hasn't had to deal with historical baggage. It's still the hot new thing, and that just won't last. 1) Concurrency model : there are plenty of C++ frameworks doing various concurrency models. As long as you do what Go does, and only use that framework, no linking to other stuff, it works beautifully. Already, the standard library is making allowances for other synchronization primitives (look at the sync package) Of course, in C++, you'll be sorely tempted to link in code with other concurrency primitives. Especially when it comes to having 2 kinds of event loops, you really shouldn't do that. It doesn't help that a lot of large companies felt the need for 2-3 proprietary C++ event loop systems. Fortunately, most libraries aren't parallelized, so it doesn't really matter what event loop system you run them under. Also, from working with other concurrency models ... I miss a lot of stuff. Futures ... oh my God, does Go need that (why doesn't "go func()" return a future ? AARGH). Limiting resources for specific functions like java's executor framework ... when you need it, there's no going without it.' Also, select is a horrible way to implement protocols (rules-based communication between either different parts of the same process or simply other parts of a distributed system). Implementing a protocol as a set of methods that can be called on a given object, with or without remote object references works much better. Incidentally, this is what all Go protocol libraries do (google protobuf, cap'n proto, flatbuffers, ...). I understand why they choose this approach over the "native" Go approach : select isn't useful for anything but the most basic of protocols. If you have more than 2-3 message types ... things start to get completely out of hand with select. 2) only one way to format your program correctly ? I think you'll find that gofmt in fact leaves many questions unanswered. Line break or no ? Up to you. Where ? Up to you. Full syntax for struct initializers or short syntax ? Up to you, gofmt won't change it ... What I will credit gofmt with is popularizing the concept, and getting code formatters much more opinionated in other languages, and that is a very good thing. But LLVM's C++ formatter and autopep8 are superior in functionality to gofmt for their respective languages. 3) I have seen at least 5 different JSON serialization libraries in Go. There's 3 broad approaches. You can either use reflection on structs and then use that to decode JSON. Trouble is, this is slow ... very very slow. It's as slow as the next option, but doing things this way does mostly ensure correctness (doesn't deal with various kinds of ddos though). There's just "decoding" JSON into map[string]interface{}, which is about as fast but it can deal with fields unknown at compile time, which can be important if you're making something that, say, just checks one aspect of requests (e.g. security, or load balancing). The huge disadvantage is casting interface{} to what you need every time. And finally there's precompiling a given JSON format into a Go library, which is a LOT faster than either of the previous approaches (but also can't deal with unknown fields). 4) Package management ... lacks versioning. There's no guarantee your code will compile 6 months later if you use Go's own package management. In fact, given just how in flux everything still is, it's pretty much guaranteed to not even compile. Also, a number of Go advantages are only advantages because Go is only beginning to exit it's honeymoon phase. Go libraries, whether builtin or on github, are "v1" designs : they're consistent, they don't have historical crap in them, they don't have 20 unforeseen but necessary usecases crammed in in extremely uncomfortable ways. Not yet, that is : the honeymoon is ending. Bad design decisions do bite larger programs on occasion (such as Go's logging not using an interface, which can bite you, leaving you with little choice but to reimplement logging for your project/company). This means that while things are pretty good now when it comes to the standard library and most github libraries, they're getting worse fast. Go libraries are written by enthousiasts mostly at the moment. So while ignoring errors occurs regularly in those libraries, it's not yet like C, where every single error is ignored in the vast majority of libraries.
- actsasbuffoon 11y agoI'd contend that abstraction is perfectly fine, so long as it's an abstraction that people reading the code are likely to be familiar with. In Haskell, I'd prefer someone just use a monoid when appropriate, rather than reinventing the wheel. That said, you might want to avoid some of those Haskell niceties when writing Scala (as my co-workers keep reminding me) because those abstractions are less familiar in the Scala community. As always, the key is to tailor your message to your audience. That's just as true when writing code and choosing your abstractions.
- jeffreyrogers 11y agoFrom what I've seen most of the times people complain about Go it is because they think they're going to use whatever feature they claim is lacking when in actuality they rarely use it in practice.
- aikah 11y ago> when in actuality they rarely use it in practice. Because they can't at first place since it is lacking. If it wasn't lacking they would design their code around this "whatever feature" they feel is needed.
- deleted 11y ago[deleted]
- aidenn0 11y agoI like rarely used features. A language having extra features doesn't make it worse. I've used maybe 5% of the python standard library, but that fact doesn't make me feel like Python is worse.
- shadowmint 11y agoWhenever I work in Rust, I find myself having a good time mucking around with the abstractions, but not really getting anything done toward the problem I’m trying to solve. I hear this a lot. There's a lot of good stuff in rust, but people seem to get massively caught up in making the borrow checker happy and lose sight of the actual task. Maybe the idea of a drop in GC type for rust (ie. https://github.com/Manishearth/rust-gc/ https://github.com/Manishearth/rust-gc/) has some merit after all...
- eddyb 11y agoA safe GC would be immutable by default, so you end up with a lot of Cells (or worse, RefCells) to emulate a mutable GC like JS or Go.
- Manishearth 11y agoPretty easy to do `type MyGc<T> = Gc<RefCell<T>>`. Even better, put trait objects everywhere. Now we're Java. Go sit in a corner and think about what you've done :P When designing rust-gc with mystor at one point I joked about writing a syntax extension that converts everything in a crate to a GCd, RefCelld, trait object, so that Java programmers have no problem converting.
- pcwalton 11y agoThe original post was talking about abstractions. The borrow check is not an abstraction.
- shadowmint 11y agoOk, sure: Making the borrow checker happy with their abstractions... You've seen iton #rust too, Im sure. People trying to make a genric reusable thread safe Foo and getting stuck with the borrow checker rather than making a specifc solution to a problem that uses unsafe or whatever and actually solves the problem. I know Ive seen it several times. Safe good code is better, but it's also a distraction in many problem domains.
- bmurphy1976 11y agoI just want to add my 2 cents. Abstraction is fine, and useful, however every abstraction comes with a cost. Even if you can't see or quantify the cost that does not mean it isn't there. It only means you have not done the work to fully understand it. It is your job as a rockstar dev to ensure the benefits of using abstraction outweigh the costs. And that brings us to Go. Go is a perfectly capable language. Like most it's good at some things and not so good at others. If you approach it expecting Haskell, you will fail. If you approach expecting Go, you will have a much better experience (assuming you are working on a project that is a good fit, once again, your responsibility). I won't tell you to use or not use Go or Haskell. They are both awesome, and they both utterly suck. But you know what? That's life. That's how it is always going to be. Pick your poison.
- aikah 11y agoAnd fortunately , there are plenty of alternative languages (D, Rust, Nim, Crystal,...) , so let's promote them instead because any criticism Go will fall into deaf ears anyway.
- sdogruyol 11y agoYeah,especially Crystal is gaining traction and lots of good commits are coming in.
- ebiester 11y agoIs Crystal's whole point to be a staticly typed Ruby, or is there more to it? (I guess I'd just like some of the things we've learned from functional type systems, such as pattern matching, which I don't see up front.)
- sdogruyol 11y agoWell that's the starting point. Currently more ideas are forming up and being baked into the language. For example Crystal is removing explicit Threads and switching to Channels as the main concurrency model.
- excepttheweasel 11y ago> In many cases, that up-front cost is paid back many fold later, when other programmers (or you yourself, after you’ve forgotten the details of the code) come and try to read and work with the code. Go optimizes more for understanding the code later than for building big things quickly. I believe this sounds attractive in part because programmers are so excited by the idea of solving problems, and it's true that a specialized implementation can always beat a general one. But it does not sound particularly sustainable. A language that doesn't provide adequate abstractions often results in requiring its users to develop those missing abstractions over and over again. With the requisite possibility of bugs or implementation naivety. As both a Rust and Go user, I do find the talk of generics a little over played. Go has great facilities for code reuse that often mean you won't miss generics as much as you might think. But I also see Go projects growing in size quicker than I can appreciate. The increased volume of code, each piece being specialized for its particular purpose - harder to fit in my head at one time. The cost of changing the code becomes more severe, each instance of an abstraction in the code being different enough to warrant specialized attention, rather than fixing code in a single place. In every organization I've worked at, as the size of a code base grows, so does the cost of change. A language that doesn't scale well is only going to exacerbate that problem. Perhaps Go seems great now because we've yet to really see any projects written in it at this scale.
- duggan 11y ago> That said, for some projects I’d prefer Rust. Specifically for very large projects, a heavier reliance on abstractions starts to make more sense. This is an interesting point, because I've never actually worked on a large project that shipped. Lots of brow furrowing and hand wringing over correctness, but at the end of the day nothing for customers to use, or too late for it to matter - which is more or less the same thing. Conversely, I've seen plenty of small "shim" projects that grew, sometimes rapidly, into much larger projects. Few, or no tests. Awkward, meandering blocks of logic, often with developers lamenting the lack of good abstractions (myself included). Large projects tend to be second systems, and second systems tend to suffer second system effects. It seems as though the profession of software development curses its practitioners to remain unsatisfiable.
- nickbauman 11y agoI've worked on many (if not all) parts of systems that are over 1,000,000 SLOC written in languages like Java and C++. I always felt that if I'd used a more powerful language those systems would be expressible at a 1/5 to 1/10 the SLOC. Once I discovered Lisp, I found that more powerful language. In my experience (I'm now a full time Golang developer) for the things that Go does well, Clojure creates much smaller amounts of code and performs at least as well. When I program in Go, I revisit my younger self again feeling the same frustrations. I don't see Go as The Way Forward except for small "infrastructure" programs in the M2M space.
- Denzel 11y agoI've never been a Go evangelist. For years, the appeal and praise lavished upon Go flummoxed me. Until I decided to use Go for my latest product. Then it made sense. For most purposes Go is "good enough." And it's good enough in enough areas for me to set Go as the standard, de facto language at my company, unless there's a damn good reason to use another language. I appreciate Go because it's fast, small (re: syntax and standard library), garbage collected with nice primitives (pointers and slices), concurrent with high-level primitives (goroutines, channels, select), expressive enough (strings, maps, range, first-class functions, type system, etc.), first-class support for Unicode, and it has a rock-solid standard library. About a month ago, I started learning Go. It's so small. The language, the standard library, the tools. They're all so easily digestible; it took me 4 days to work through the Go playground, read the entire Go specification, work through and learn 40% of the standard library, and start writing production-ready programs. C was the last language that enjoyed a language/standard library this small, to me. The same thing can't be said for Ruby or PHP, or any other languages I've worked with. In almost every project I've been involved with, there would be usage of some arcane corner of the language. Whether it's determining the byte offset of a member function in C++, or the GCC extensions to structure initialization in C, or metaprogramming magic in Ruby. All these cracks and crevices are difficult to keep in your head. This isn't so with Go. It's easy to keep the entire language and standard library in your head; providing a certain ease and flow when building a program. Ease of use applies to memory management as well. Go offers just enough control over memory to make it pleasant to implement and use real data structures. Try implementing an LRU cache in Ruby/Python that evicts based upon an object-size policy without wasting a ton of memory simply maintaining a linked list. When I built a distributed real-time, type-ahead service in Ruby I was fighting the language the whole way when it came to simple data structures, memory management, and concurrency. (It was just a prototype, I know Ruby wasn't the right tool.) Originally, I was going to rebuild the service in C++, but that would've taken too much time. Instead, I opted for Go and it was much easier, and obviously much more performant. Not as performant as an equivalent C++ service, but performant enough. I don't think much needs to be said about Go's concurrency. First-class primitives such as goroutines, channels, and selects along with solid standard library support in sync and sync/atomic, makes for a powerful combination. Go wraps these concepts in a very bland, mainstream way. Making them more accessible to more people with little time investment. You're right, Go will not win based upon the # of LOC written. However, after writing 20k+ LOC in Go over the past month, I don't see any reason to write any of our back-end code (infrastructure, services, web servers, tcp servers, etc.) in anything other than Go. It's good enough in enough areas to make it much faster for a team to standardize on just this one language. Not only does this reduce the time wasted due to context switching between languages in a polyglot shop, it makes it a ton easier for anyone to jump in and contribute anywhere at anytime. --- To give my thoughts some context, here's a subset of my professional and personal language/project history: - Ruby: 100k+ LOC Rails monstrosities and smaller 20k LOC projects - PHP: 200k+ LOC bare-PHP e-commerce websites and 50k LOC CodeIgniter/Laravel intranet apps - Python: 10-20k LOC utility and server management scripts - C++: 500k+ LOC open-source 3D game engine and multiple <10k LOC personal projects - JavaScript: ~35k+ LOC for the front-end work on some websites I've worked on - Common Lisp: read all of Practical Common Lisp and ANSI Common Lisp, and dabbled in a few small programs
- nv-vn 11y ago>For someone new to the codebase who knows nothing of the giant abstraction, which do you think is easier to grasp: 10 lines of code that only make sense if you know the abstraction, or 20 or 100 lines of code that can be understood on their own? The "only make sense if you know the abstraction" part seems to have it backwards. The point of the abstraction is to _not_ have to know what's being abstracted away. The problem is that with Java (which Go was being compared to here), abstractions often times aren't exactly abstracting away anything. "Abstraction" has basically come to mean "use objects because they have getters and setters!" and other things like that, which give very little benefit in general. Nine times out of ten, they do make the code more complex, because their abstractions come either at too low a level (abstract away simple functions but require the code on the outside to implement everything and reinvent the wheel) or too high a level (abstract away all operations so that no creativity is possible with this). So as a solution to the "abstraction" problem, Go does it right, but something like Rust (which doesn't try (too hard) to be like C, Java, etc.) can do an even better job at this by entirely changing the meaning of "abstraction".
- pcwalton 11y ago> Whenever I work in Rust, I find myself having a good time mucking around with the abstractions, but not really getting anything done toward the problem I’m trying to solve. A couple of points: 1. Realistically, this is a programmer problem that no language can solve. If you don't need the abstractions for the code you're writing, don't use them! This is hardly something unique to Rust. A common complaint that experienced Go developers have about new Go programmers is that they overuse channels and goroutines--mechanisms of abstraction (of control flow, broadly construed). But nobody is arguing that Go would be a better language without channels and goroutines. The solution is to train new Go programmers to stop overusing channels and goroutines and to focus on the problem at hand. That's the same advice that I would give to anybody thinking about the perfect generic way to solve their problem in Rust instead of getting the job done. 2. Generics aren't exactly optional in Rust. Let's assume for the sake of argument that generics are a bad feature that languages should not have (something I completely disagree with, but in any case). Even supposing this were true, it's not like Rust would be a better language without them. Rather, the language could not exist, because it would be impossible to satisfy its core goal of zero-overhead, runtimeless memory safety. You couldn't have smart pointers without generics; you couldn't have iterators; you couldn't have Option; you couldn't have any functions that take and return pointers at all because lifetimes are a form of generics. Go is able to get away with not having generics because it leans heavily on having a runtime to support the built-in data structures and on garbage collection to make memory management decisions at runtime. Not so with Rust, which is designed to bake all that information into the compiler to avoid the overhead of a runtime and of garbage collection.
- Veedrac 11y ago> Realistically, this is a programmer problem that no language can solve. > The solution is to train new [language X] programmers There is high demand for software that blocks "procrastination" websites, because people struggle to focus when the whole internet's around. I know someone who's hidden their computer charger in order to stay focused. I've read a surprising number of blogs about aiding writer's block with minimalist text editors. I even know someone who needs to offload finances to another party lest they spent it too quickly themselves. You can tell people they just need training, but if the whole standard library screams "abstraction!", people are going to abstract. A language like Go is the minimalist text editor of the programming world. Sure, some people will scream they need their MS Word macros and floating panes (and it's even more true in CS), but these tools are an effective treatment of the symptom nonetheless. > Generics aren't exactly optional in Rust. Sure, but this doesn't change the trade-off. One should use Rust where the problems it solves best broadly match with the problems you're dealing with. And, IMHO, Rust is an exceptionally high complexity language for small projects.
- sprash 11y agoNim (http://nim-lang.org http://nim-lang.org) is far superior to Go and Rust in many ways.
- MichaelGG 11y agoNim is interesting but isn't remotely like Rust. It doesn't have memory safety as a core goal. And there's no strong sense of design and elegance. It very much comes off as "here's a bunch of ideas thrown together with the restriction that they all must somehow compile to C". I'm not saying it's bad or its users are wrong, but the mindset is utterly different. Rust and Go don't belong in any comparsion really. The only reason they are compared is because Google co-opted the term "systems" to mean something different than everyone else. Go fits in much more compared to managed languages, like Java or OCaml or something. (Just because Go statically links its runtime into output binaries doesn't change things. You can do this with C# via Mono's AOT features, for instance.)
- burntsushi 11y ago> The only reason they are compared is because Google co-opted the term "systems" to mean something different than everyone else. Really? You know, for a fact, that that is the only reason the two languages are compared? There couldn't be any other possible reason? How many years has it been since the official literature made such an egregious and offensive mistake as to misuse the term "systems"? The only reason it's even an issue is because people insist on bringing it up as the root cause for [insert social phenomenon here]. Because clearly, anyone who compares these languages must be so enamored by the original description of Go as a "systems" language that there couldn't possibly be any other explanation. (But maybe this fits in just right with your view of the Go community as "anti-intellectual.") Maybe people compare the languages because many people find them comparable. There's no mystery there.
- matthewmacleod 11y agoThere's no mystery there. Contrary to the previous poster, I suspect people simply compare the languages because they appeared around the same time and are both backed by big players. There's nothing really comparable between them (although the that's just my opinion) and I'm baffled as to why they are co pared so often.
- MichaelGG 11y agoI wonder if Go is taking off due to folks coming from Python and Ruby, looking for something that has better perf and concurrency. Sorta like how Python got a lot of Java users that were just sick of the boilerplate. The fact he compares Rust and Go is bizarre - they're totally different types of environments. Why not toss in OCaml and Java, too? Go is a managed runtime language and "systems" is only mentioned due to misleading marketing when the language launched. And of course Rust might feel a bit harder - no runtime means you gotta do all that stuff at compile time. Kills the chance for some shortcuts! People go on about how Go is practical and you don't need features, really. But that's a lame excuse. Facebook was built on PHP. Transport Tycoon was written in x86 assembly. Harry Potter was written with pen and paper. So you don't need. The attitude from the Go community is almost like an anti-intellectual one isn't it? F#'s inventor said it was hard getting generics into .NET because Microsoft viewed it as "academic and experimental" despite it being old ideas put into practice. Yet another decade later and Go is further promoting this anti-progress attitude. (I'm not really against Go, just disappointed in how weak available language technology is.)
- commentzorro 11y ago> The attitude from the Go community is almost like an anti-intellectual one isn't it? I hear you. There was a funny post a couple years ago weighing a bunch of languages on republican/conservative vs. democrat/liberal scale. But the author erred with Go. Go is certainly the most republican conservative language out there today. Go not only adopts the anti-intellectual stance but comes across as a language that's controlled by "religious leaders" who dictate not only the the direction of the language but its "morality" too. And those who use the language feel the same hidden pressures from constraints. This leads to a weird state of having to "believe" in a language and defending things: "like less is more", "choices are bad", and having others determining what you want and need. And this is the most annoying part. Because Go is really not a bad language. It's simple and constrained but easy to get into and easy to get stuff done. But Go's the whole attitude comes across as somewhat off-putting to window shoppers who might actually purchase and be fine with it otherwise.
- djhworld 11y ago
- cschep 11y agogreat ending! "Typing is not what makes programming difficult."
- coldtea 11y ago>For someone new to the codebase who knows nothing of the giant abstraction, which do you think is easier to grasp: 10 lines of code that only make sense if you know the abstraction, or 20 or 100 lines of code that can be understood on their own? I'll take those 10 lines of code. We've only managed to build powerful systems because of ever increasing abstractions. See Alan Kay's DSL research for example: http://www.vpri.org/pdf/tr2007008_steps.pdf http://www.vpri.org/pdf/tr2007008_steps.pdf It's not like every system with abstractions has to be done the Java way. Functional programming, be it Haskell or Lisp etc, has tons of abstrations too, and they don't get in the way. I'd say Java's issue wasn't abstractions per se, but uneeded abstractions, BS boilerplate and needless ceremony. Which Golang also suffers from. Besides, you don't just dispose of the abstractions and get the same, but now straightforward, code. You get rid of them and get 10x the code (the 100 lines compared to 10 he mentions), which you have to keep track of and keep in your head, only now you don't have high level abstractions to help you in that, you have to do it manually. (And of course Go vs Python is not a good comparison, as Python's lack of types make it difficult to reason about large programs quickly. How about Go vs C#/Swift/D etc? I'd take Swift any day of the week.
- danneu 11y agoThere are always trade-offs. For example, I'd rather read explicit 100 lines of explicit SQL than the 10 liner Active Record abstractions I've had to come back to on my old Rails projects. It turns out that the 10 liner forces you to keep much more in your head (the whole Active Record abstraction, its idiosyncrasies, its edge cases, its performance profile) than the 100 lines of explicit SQL that let you bootstrap a mental model without having to credentialize in documentation every time you touch the project. I'd also rather read 100 lines of explicit authentication middleware than 10 lines of Devise configuration (a Rails authentication gem) for the same reason. The appeal of "keeping less in my head", as we put it, is one of the main reasons I use small frameworks these days.
- davidp 11y ago> And of course Go vs Python is not a good comparison, as Python's lack of types Nitpicking: Python has types, they're just dynamically determined instead of statically. That said... > make it difficult to reason about large programs quickly ... I agree 100%. At $DAY_JOB we have a very large Python codebase and it can be extremely hard to understand what's going on, let alone refactor safely. I really miss static typing.
- slantedview 11y ago"In real-world code, you don’t actually end up casting interface{} to something else that often" I have to disagree here, and I've had trouble finding any serious argument that this is an OK thing to have to do. When we accept the benefit of not allowing users to create generic abstractions, we also have to recognize the very real cost of not allowing users to create generic abstractions. Software/technology trends go in cycles. Several years from now, a generation of Golang programmers will be preaching the benefits of DRY, having learned from the painful mistakes of maintaining the large and complex Golang codebases yet to come without the benefit of creating appropriate abstractions, just as Golang was partially an answer to the painful mistakes of maintaining large and complex dynamic codebases. And so the pendulum will swing again.
- jodah 11y agoIt's been interesting to watch similar arguments being made of Golang, over and over. From a casual user's perspective, it seems to optimize for (what is to me) the wrong thing, which is readability over maintainability. Without the ability to create abstractions we run the risk of having to re-learn the lessons of the past, about DRY and SRP and all that jazz. While more language features give users more rope to hang themselves with, less language features constrict the ability of larger projects to manage complexity, such as is the case with dynamic languages. For Go, I sense that this will become more obvious over time. TLDR; Readable code is nice, but maintainable code is better.
- meowface 11y agoI think if/when Go adds some form of generics (beyond requiring code generation with comments...), it will truly replace Java.
- djhworld 11y agoI like Go, I've coded a few personal projects in it in the past, and generally like to keep up with the Go scene when I can. However, I can't help but feel that if people want it to replace Java, then they need to make a robust IDE like IntelliJ or Eclipse. I'm a Vim user at heart, but when coding in Java I find IntelliJ + IdeaVim plugin to be very productive. It goes far beyond just the classic auto-complete too, IntelliJ does a lot of neat stuff like suggesting updates to the code, or creating fields/methods and refactoring just as a simple key combination.
- douche 11y agoIf Go has any legs, I'm sure that JetBrains will get around to building a version of IntelliJ for it. They've even got empty space for it in the IDE section of the products menu on their site :-)
- tylerpachal 11y agoFor the meantime, there is a very nice Go plugin for IntelliJ products: https://github.com/go-lang-plugin-org/go-lang-idea-plugin https://github.com/go-lang-plugin-org/go-lang-idea-plugin
- Mikeb85 11y agoThe timing is funny, I just started playing with Go a few days ago (the 1.5 release as well as the impressive amount of software that's actually been shipped with Go convinced me to give it a go - pun intended, somewhat). I must say, its a great little language. Love the tooling, the dependency management, it was even incredibly simple to set up the dev environment (basically just DLed the binaries, added to my path, installed the Go-plus package for Atom, and everything just worked). It is a little shocking to work with a relatively bare-bones language since I work mostly with R (which has a package for everything it seems), but its been a lot of fun. I'll probably do something bigger with it in the next little while.
- bsummer4 11y agoThe article spends a lot of time talking about how "Complicated" abstractions are, and about how abstractions come with a complexity cost. IMHO, the opposite is true. > Whenever I work in Rust, I find myself having a good time mucking around with the abstractions. Good abstractions, the kind you use in Haskell and (presumably) Rust are simple, non-leaky, and exist to enable simple, correct code. It's true that abstractions, even good abstractions, take time to learn. However, once you've digested them, you'll see them everywhere, and you can continue to use them for the rest of your life. Functors, for example, are a foundational abstraction. They are extremely simple, extremely powerful, and will relevant forever.
- rumcajz 11y agoThere'a real problem with abstraction. Look at any Java code. If you haven't seen it before you are going to deperately browse around the code to find out a single line that actually does something. But all you see is scaffolding. When you finally find a line that does actual work, it's not clear how it connect to other such lines. There's another such line 1000 lines below it but all the abstraction makes it almost impossible to find out how are the two executed. Which one goes first? Is one of them optional? Et c. In general, abstractions are used to capture programmer's understanding of the structure of the program (it's more or less like boxes and arrow sketches in your notebook). But then, programmer's understanding of the structure of the program is often inadequate and lacking. As your understanding of the problem improves, so does your abstraction. But by then, it's hard-coded and cannot be easily changed. Many times I've seen how new functionality cannot be implemented because it doesn't fit the abstraction and re-writing the abstraction would mean re-writing the whole project.
- tome 11y ago> But all you see is scaffolding. When you finally find a line that does actual work, it's not clear how it connect to other such lines. There's another such line 1000 lines below it but all the abstraction makes it almost impossible to find out how are the two executed. Wow, but as you say, that's "scaffolding" (or "boilerplate"), not "abstraction".
- rumcajz 11y agoAs I understand it, the scaffolding in Java exists to express astraction, no?