The site isn't really about dogs, it tracks a few dozen different topics that people consider difficult.
It's not so much about any longstanding personal policy, but if your dog of 10+ years had just died recently, and you sat down to watch a movie to relax, you might not want the movie to feature a prominent animal death, for example.
I use the site mentioned in the article almost every time I want to watch a movie. Its easy to dismiss it in terms of "pampering" or being too soft, but there are people who have lived and seen horrible things and do not want to be reminded of them.
It's also great as a nutrition label for media of sorts; "is this movie appropriate for a small get together?" is a question that's often hard to answer without a service like this.
I absolutely agree. Some of the categories may be out there, but there are some very real and very helpful warnings/descriptors on DTDD. One time I was going to watch Annihilation with my friends, but checking DTDD showed it was more body horror-y than any of us were ready for that night. We came back to it a while later knowing that and all thought it was a great movie. Sometimes, just going in with the knowledge so you can brace yourself is helpful.
They've fixed the import / modules situation to a point where it's usable and much improved, and generics have been added.
However, the issue this brings up about structs / types not explicitly declaring which interfaces they implement is a real and unaddressed problem, especially in large codebases. The only tool that I'm aware of that finds implementations is GoLand, at steep JetBrains prices.
Figuring out what type an API is asking for should not require reading every line of code in the package, and slows down every developer of large Go projects
When developers who usually make 6 figures of money complain about $90/yr IDE price I just cannot help laugh. Actually it's even better... the price elevators down from $90 -> year2 90 - 20% -> year3 90 - 40%.
Over three years that's like $150-$200 total and it will save you so many headaches. But that's a steep price? Are you kidding? Why do developers hate tools that cost money when they save them time and allow them to do more?
Sorry, no. I have JetBrains and have since stopped using it for go development. It's too slow, too buggy, and lacks the ecosystem that VS code has. I still use it for Java because the rest are even worse
A language that depends too much on IDE integration for usability is a real problem, because now you have tool fragmentation as everyone goes different routes with varying levels of success to fix the deficiencies in your language. In the end you end up rolling your own tools as I have done, which is the absolute WORST of all worlds.
Go was supposed to be simple, but all it succeeded in doing is shifting the complexity elsewhere and calling mission accomplished. When you're designing a language, it's VERY important to understand the difference between the emergent complexity of the domain, and the inherent complexity of your design. The latter can be fixed, the former can only be managed - in ways that are already well researched (or just swept under the rug, as go has done).
Too much magic and too much "clever" re-purposing of existing paradigms (file names, capitalization, implicit contracts, etc) makes for an infuriatingly bad design.
I like working with Free and Open software much more than proprietary software. I think it's important for society, and I have more fun that way too!
Also the payoff for me has been very good, I can learn emacs once and enjoy using it for the rest of my life for all significant written language tasks on a computer.
Perhaps I could be a little more efficient if I were using a jetbrains IDE, but then I wouldn't like what I was doing as much. Enjoying what I do, even if it may look slightly contrived to others, is important in me achieving results at work.
This argument is not convincing to me, especially considering JetBrains publishes their IDE base as open source.
Everytime I have to use VSC to develop typescript and angular, I am having problems with finding definitions (works 30% of the time), code search (it takes longer due to the constricted interface), git operations (want to do more than a simple pull and push? good luck), and much more. WebStorm on the other hand has a lot less bugs, a more flexible interface, and more features. I am glad that people make an effort to make an IDE instead of an editor with IDE-style features and I'll gladly pay a very small amount of my salary to them.
Every workshop has higher costs than a software developer. Imagine a car mechanic propping up a car with 2 by 4 because they use what's available for free. No, they buy their $30,000 lift because they need it to get their work done quicker.
> Every workshop has higher costs than a software developer. Imagine a car mechanic propping up a car with 2 by 4 because they use what's available for free. No, they buy their $30,000 lift because they need it to get their work done quicker.
This is a far from convincing argument. Jetbrains IDEs are not the equivalent of a professional lift and the competing (often free) products are not the equivalent of a 2x4.
Is Jetbrains good? Well, I've used it for Java and was pretty impressed.
Is it $199/year[1] better than the free stuff? Well many people don't think so. It's fine if you only every use a single stack, but most of us use multiple languages and multiple stacks, now you're looking at $649/year (see link below) for all tools. Considering that my current personal development computer cost less than that years ago, is it now wonder that the price is considered too much?
I think the problem is that developers are looking at the Jetbrains products and comparing it to the value they get from other development purchases.
Compare:
A single $1k computer will last for many years, do every single development task needed to make money, be used for entertainment, and write all the actual software that will be sold. When it is too slow for dev (in a decade from now), it'll be repurposed for something else.
A single annual payment of $649 to JB results in a tiny increase in dev speed, which will disappear at the end of the year anyway. It won't make the code more robust, it won't help solve business problems any faster, it will only make code navigation faster.
For a dev, look what $1000 buys, and then look at JB for $650, and it doesn't look like all that good value for money anymore.
Just wanted to note that if you're talking about "personal development computer" and "developers loooking ... and comparing", then it's more like an "individual" license as opposed to the commercial one, which is meant to be evaluated by companies.
The individual-license pack for all of their IDEs would set you back $250 as opposed to $650 commercial license.
I used to use "IDEA Ultimate", which is 30% cheaper than the All-Pack and supports installation of most of the other language plugins, allowing me to use a single IDE for everything. Nowadays I'm using separate IDEs as that seems to work faster.
I personally find the price worth it, as even a simple "expand selection scope" operation which I use many times per day just doesn't feel right in VS Code.
JetBrains' All-Products Pack costs me only 150€/year + VAT (250€ individual license minus 40% for subscribing for 3+ years) which is also fully tax deductible. In the end it costs me less than my cinema budget for a year of top notch products with proper support and bug fixing where I don't have to wait months for an answer.
I stand by my 2 by 4 comment because they get the work done, just slower and more awkward. It's always super amusing how software developers with one of the highest salaries around the world (yes, even in poorer regions) complain about costs when other jobs require tens of thousands in initial investment.
Currently that shows a cost of 250 euros per year, or about 20 euros per month (excluding VAT which varies).
For most developers, that is indeed a relatively small amount (even I opted for the ultimate package, despite earning in the low 2 figures in Latvia), whereas the 650 euros for commercial licenses would be doable for any organization that cares about their developers' experience.
Personally, whenever I see commercial software or a SaaS/PaaS/IaaS solution, I'm tempted to throw a brick through someone's window (figuratively) because those are likely to result in unreasonable amounts of vendor lock (especially with cloud services around Kubernetes management), but personally I haven't found a better IDE than what JetBrains offer.
For Java, all of the alternatives are worse: Eclipse is buggy and crashes (though some swear by its incremental compiler and integrations), NetBeans is kind of dated and struggles with projects that have 4000+ source files (though it's cool that Apache keeps it alive and there's the whole module enable/disable functionality and their VisualVM integration is great).
For .NET, Rider is easily up there with Visual Studio, even when you're doing something more niche, like working with the Unity game engine (the performance hints are nice), or just working on .NET apps.
For PHP, Ruby, Go, Python and other languages their tools feel competent and oftentimes suggest you whatever it is that you might want to do, be it setting up your runtimes properly, your dependency management systems, install all of the dependencies, import the project config/launch profiles etc.
For Node/JavaScript I have never found a good IDE, but maybe that's because the language is sometimes a mess to work with - e.g. getting only some very basic completion in some garbage 3000 line AngularJS controller because even the IDE has no idea what the hell is going on there, or having Vue 3 use the <script> tag for adding code imports, instead of detecting that i'd like to use <script setup> but then again, they're pretty speedy with updates and if you don't do anything too crazy with projects, then it should be good.
I don't have much experience with their C/C++ offerings, or their lightweight text editor (Fleet) or the likes of DataSpell, though their DB management offering, DataGrip is pretty okay too! Though you can also configure the individual IDEs like IntelliJ to show up hints for most decent frameworks.
Sure I also like to use emacs since it stood the test of the time but the point was not proprietary is better but unwillingness to support companies that sell products.
If we refuse to buy products then we end up with companies offering just services with vendor lock in. Well...we already sort of ended up in such world.
I would be more supportive of this message if it was a $90 LSP server that you could support by buying (a la intelephense), but software developers are very opinionated about their editors and not everyone wants to use IntelliJ products.
Musicians and carpenters make far less than programmers, but they still buy their tools. Software people are too entitled. Even if you are not professional, you can still afford 54c a day ($200 a year). Even a programmer in India can.
Many junior developers in my city make around $300 a month. After spending $200 on rent and most of the rest on food, you're not left with much. I understand nobody really cares about crap-holes like mine when they're making most of their money in Western Europe and North America, so just throwing it out there.
As highschool student in 80's Portugal, 10 years after 40 years dictatorship and colonial war were behind us, when software was sold as bootleg copies on bazaars, I saved enough money to eventually buy Turbo Pascal for students at 30 000 escudos.
As I wanted the real deal and not a bunch of no name floppies with copied manuals.
That would be around 150 euros, without taking into account the inflation to modern days.
And to place the price in perspective, it was a third of the minimum wage, while the overall cost of my PC took 5 years for my parents to pay back to the bank.
Because it wasn't based on bloatware liks Electron. And I guess the developers actually cared about performance because at that time they couldn't just assume that everyone has a powerful machine.
Someone apparently isn't aware that IDEs can consume build scripts as project definitions.
I don't duplicate anything, my CI/CD pipelines consume MSBuild, Ant, Gradle, Maven, CMake, XCode, package.json, gulp, webpack files just as easy as my IDEs.
I'm tempted to ask what languages you're using and what has your best experience with them been like.
Because as messy as Java is, refactoring codebases in it that have been kept alive for close to a decade is surprisingly not madness-inducing (most of the time), at least in some of the sane frameworks. Apart from, you know, legacy projects basically killing your career in the long term.
I'm not sure what other language I'd feel comfortable with changing how some method works across 50 other places that call it and have the IDE do most of the heavy lifting.
Yes, I have Stockholm syndrome, probably. Yes, I'd prefer to retire to planting potatoes in a farm, rather than work with NullPointerExceptions.
How much would a carpenter pay for a fancy bench top for their workshop? I'm guessing not a lot, since they can make one themselves.
Programmers are toolmakers, and are therefore harsh critics of tools they use; just like a carpenter will tell you everything that's wrong with the design, and choice of wood that went into a pricey, but ultimately-affordable-to-a-carpenter bench top. Having access to cheaper, good-enough alternatives is part of it.
> A carpenter is not going to make his/her own table saw.
This is where the analogy breaks down, but they'd likely download a free one made by a consortium of other carpenters, which can be customized to their needs
> I do pay for tools that I need.
As have I: I was paying JetBrains yearly until they published plans to brick my IDE if I dared stopped sending them money. They walked this back after an uproar - but that episode showed me that I was also playing in their sandbox and subject to their every whim. I now default to using tools that can be forked at a moments notice (by myself or others)
Also, JetBrains IDEs were far ahead of the competition back then. For the tech stack and codebases I now work on (or perhaps additional experience?), none of the JetBrains IDEs are worth the effort. vim and a handful of plugins & scripts are adequate 95% of the times, VSCode takes me up to 98%, and it's diminishing returns beyond that
This is an undue attack. We buy our computers and screens and keyboards, most of us are on commercial OS, we pay for SaaS at a non trivial price, and most of us also use additional personal apps that aren't free (including password managers, mail clients etc.). Those are actual tools for the trade.
Arguing we should also buy every Jetbrains product is like arguing carpenters should buy line drawing AR goggles. Perhaps some will see the value in it, but it's far from an noncontroversial POV. If you feel a tool as as much downsides than upsides in your workflow, you don't use it, whatever its price is.
“I’ll pay $1000’s to get all setup and running with everything I need, including a bunch of stuff I don’t need, but not the last $90 for some productive software to make more money”
Some people really like these tools, and that is OK. But not everyone has the same workflow. I personally get a JetBrains license from the project I work on - but I refuse to use it, as I find their tools pedantic, slow, and eating my computer's resources. Ymmv.
Oh absolutely, if someone perfers emacs or vim, VS, VSCode, some JetBrains IDE. Punch cards.
Whatever makes them happy and productive, that's great. I've seen people use Vim and its crazy how productive some people are with it.
My point is complaining about the price of some software like it's blocking them from doing anything. They spend all this money on all this hardware and software, but when it comes to development, oh it costs too much I don't want to pay $90 for something to earn money...
The initial [0] only mentioned the steep price in passing, and primarily lamented the inefficiency of the design. I'm not even sure from that phrasing that implying isn't a paying user, even if they seem to care about people who wouldn't fork the money for the editor.
Is this a JetBrains commercial account ? Am I at fault for not liking their product that much, and thus not paying them their apparently deserved yearly subscription ?
This feels pretty weird to be faulted for using other companies' products. And no, switching to Jetbrains' doesn't make me more money. Could be the reverse from my past trials.
It's not about liking or not liking a product. You're complaining about pay for a product. If you like a product and its helpful why are you against paying for it?
> If you feel a tool as as much downsides than upsides in your workflow, you don't use it, whatever its price is.
↑ that was in my answer (with the typo, on the “as as” instead of “has as”, my bad)
You might be confounding mine with another comment. I recognize the talent and expertise of JetBrain’s staff, but don’t like their products in general, and use VSCode as a primary editor, and (paid) Textmate for the rest.
To your general point, looking at project like Bitwarden, with their initial kickstarter and their current revenue, I don’t feel like people are restraining from paying for useful software, even when it has a generous free tier.
That depends. If you have multiple large projects open at the same time, it'll eat a lot of RAM, even if it won't be too CPU intensive.
I run it on a ThinkPad that has 32 GB of RAM, when I have about 6-7 instances of the IDE open and all of these services running locally (generally Java projects, the largest of which is around 4000+ source files), then it gets close to the resource limits.
My ThinkPad with 32GB of ram with 5+ instances of Rider, and DataGrip, VSCode, all open, switching between instances is quick. (checks number of source files for top 3 projects I work on daily) with 4684 files, 10230 files, 7211 files. (no npm junk)
Switching between Visual Studio is 15-20 seconds of wait time while it decides if any files have changed.
No semi-successful professional musician is so bare. Software engineers are not your average starving type of people (unless they are willingly doing intermittent fasting!)
And if we try to re-sell our equipment to try to recoup some of that cost, best you can get is like 1/4th the original price typically by the time it's time to sell
Putting fundamental features of the language behind a price barrier at all will keep students and people who want to experiment with the language out of the ecosystem. This isn't a papercut, it's an intentional omission that has backfired and can only be fixed by tooling. If the only way to access an often necessary feature is proprietary, why not make the whole language proprietary at that point?
any company will let you expense a few hundred dollars for a tool you use literally every day many hours a day. if you’re having trouble they are not good to work for or you’re asking the wrong way
> if you’re having trouble they are not good to work for
That is true, but also in some places that is also the status quo: especially in countries where the developers don't get 6 figure salaries and don't create as much value to their respective companies.
I dunno I've been in plenty of situations where a department head will literally beg me to buy things so they can reach the same budget spend as last year so their budget isn't slashed (DoD), and have seen the same situation in VC-backed startups looking to come up with tax write offs. Businesses for the most part love spending money and would rather do that than pay taxes, which is definitely a problem with corporate society these days.
They're spending $100 to invest in the growth of their company, which is quite different from "love spending money" or "begging for something to buy" to reduce their taxes.
In most cases you cannot use personal licence on a company hardware. JetBrains also have separation between individual licences and organization licences.
JetBrains allows users to use personal license for work, but declines company to buy cheap personal license. I think this is good pricing. I agree that make company to buy license is annoying.
I'm not talking about the distinction between free non-commercial and commercial licenses. I'm just talking in general that it's tough to get companies to purchase any software.
I'm shocked at how often I see software engineers not paying for Sublime Text. These are people who get paid to write software not paying for software.
Photoshop being easy to pirate was a feature for Apple: the uptake was absolutely insane across all possible levels and eventually nobody uses anything else. Same with Microsoft in 90s: when students asked Bill what he's planning to do with the whole China copying it, he replied that let them get used to it and we'll find a way to charge later.
I think a tool like GitHub Copilot is worth far more than $90/year and I'll gladly pay for it. Probably up to $500/year or even $1000/year I'd pay for Copilot. It has saved me so much headache and time. There's no real competitor for that product and I'm looking forward to it going GA. I'd use emacs/vim and Copilot any day over an IDE.
But I'm not sure any IDE is worth $90/year when VS Code is free. The extensions for VS Code are next-level, especially the SSH extension. No other IDE comes remotely close to how well that extension works for its use case.
> However, the issue this brings up about structs / types not explicitly declaring which interfaces they implement is a real and unaddressed problem
You can do this with a line of code below the struct definition, something like:
var _ <interface> = &<struct>{}
The compiler will also generate helpful errors if the struct doesn't implement the interface.
Not requiring struct definition is a great feature in golang. I'm able to add an interface to a struct defined in another library to inject a different implementation for unit tests.
It would be cool though to be able to optionally declare the interfaces implemented by your struct, for documentation and tooling purpose. Also to validate that the struct you’re writing actually implements the interface you have in mind. I know you can make an anonymous assignment to check that, but some sugar on that would be nice.
It's more than that though. There is just no standard library to be spoken of. I mean things like the most basic string processing methods, etc., are left to the programmer to sort out themself. Every time I've done contracting work on Go projects, I'm shocked by the things I have to implement from scratch (not that it isn't fun) that we take for granted in every other modern compiled languge I've tried (Rust, Crystal, Nim). I know this is more of an environment thing than a language thing, but in practice, language and environment are so intertwined it's pointless to not consider them together.
Another big area that is lacking is Go makes it so hard if you want to use something other than a primitive as a hash key (Rust is guilty of this as well, mind you). This is something that should come out of the box in any modern language in my opinion.
Seems easy enough to me? The only annoyance is if a third party type didn't implement Hash, but you can solve that with a manual implementation instead of a derive.
ding ding ding! This has been a problem for me a number of times. The quick workaround is pray that it implements Debug and in a reasonable way and take the hash of the string instead
not if it doesn't have equailty defined. Then you have to define it. Oh, and it's an AST node someone at X company wrote and there are 100+ node types. Have fun!
In crystal there is a reasonable data-based default hash implementation that you can just rely on.
The map key type can be anything for which `==` is defined. This includes structs for which `==` is defined for every field. Composite keys etc are trivial.
Yes, and it's missing tons of things we take for granted in other langauges. If you look at the "strings" section it's so short. There aren't even convenience things like string reverse.
Odd, I find the standard library very full-fledged and useful, including the strings package. I've almost never needed to reverse a string, except in interviews. :-) The stdlib has a full (and good) HTTP server with HTTP/2 and TLS support, HTML templating, excellent I/O support, compression, even image encoding/decoding and drawing. That said, the container types are pretty sparse, but that may change a bit now that generics are here.
What, apart from string reverse, do you miss for real projects?
The fact that it's a bunch of top level functions also makes me think of PHP from the early 00s, only I was able to do more with things then tbh. Just feels super archaic.
Not that person, but I'll call out a few issues I've had with the go stdlib:
First, it has a lot of useless packages you typically wouldn't use, like "log" and "flag" (which work, but are way worse than third party alternatives like logrus and pflag), but also like "syscall" (as it says 'deprecated, use 'golang.org/x/sys' instead), "image/draw" (nope, you wanted 'golang.org/x/image/draw' usually), "path" for working with paths (you wanted "filepath"), "net/rpc" and "rpc/jsonrpc", "plugin" (almost always a bad idea), a chunk of "strings" (use "golang.org/x/text" for proper unicode support) and so on. Some of those are marked deprecated, most of them are not, and are just waiting for someone to accidentally use them.
That's issues I have with the stdlib and not stuff I'm missing though... Though I guess I really do miss a good logging library, or at least interface for external packages to implement so I can plug in logging libraries without rewriting the world.
One thing I do find missing frequently is a reasonable set type with the ability to do things like basic set operations (intersect, diff, etc). I constantly have to write ad-hoc for loops in go to do set operations, and it's verbose, non-obvious what the code does, and easy to get wrong.
But honestly, the main thing I'm missing isn't actually a package, but more about error handling for the stdlib as a whole, which is more a language issue. I really wish I could know what possible errors stdlib functions returned without, fairly often, having to read huge chunks of stdlib code to determine that.
Perhaps 40% of the stdlib documents the error type it returns in a message (like 'os.Chdir' always returns '*os.PathError'), but for the rest, good luck. Want to figure out what errors you might have to check for 'tar.Writer.Close()'? Well, the docs says "returns an error", the interface is "error", you have to read hundreds of lines of code to figure out the possible concrete types it could be. Maybe 15% of the time, you end up having to string-match on error messages because the error var or type is unexported.
> interface for external packages to implement so I can plug in logging libraries without rewriting the world.
Well, it's structural, so you don't need other packages to implement an interface rather you need them to accept an interface. That also makes it clear it's a bigger ask - you're not asking a dependency "please also do X" but instead asking "please never need to more than Y".
> Want to figure out what errors you might have to check for 'tar.Writer.Close()'? Well, the docs says "returns an error", the interface is "error", you have to read hundreds of lines of code to figure out the possible concrete types it could be.
The concrete types it could be are unbounded, because `tar.Writer` wraps arbitrary `io.Writer`s. If you need multi-pathed error handling (usually people don't and are just making it out of habit!), worry about what things can do, not what they are.
> If you need multi-pathed error handling (usually people don't and are just making it out of habit!), worry about what things can do, not what they are.
When I'm looking at an error, it's typically for one of two reasons:
1. To set a correct status code, such as http 5xx (internal server error, our disk flaked) or a 4xx (user error, you gave us invalid input).
2. To provide a better error message, such as to localize it into an error string.
If you're building CLI tools for yourself, sure, every error is fatal and you can read english so you don't need either of those. For most go projects, both of those are relevant concerns for a large number of error paths.
Go's type-system does not help you at all.
Speaking of...
> Well, it's structural, so you don't need other packages to implement an interface rather you need them to accept an interface. That also makes it clear it's a bigger ask - you're not asking a dependency "please also do X" but instead asking "please never need to more than Y".
Yup. That is a big problem. That's the root of the error problem too, where every package returns the stdlib error interface, which is a tiny subset of what you usually want.
> To set a correct status code, such as http 5xx (internal server error, our disk flaked) or a 4xx (user error, you gave us invalid input).
For this it's simple to wrap them at return site in something that offers `HTTPStatus() int` and check for implementing that interface, not any concrete types, in your handler.
Also, those error paths should be dangerously hard to mix in the first place, you shouldn't be letting invalid input anywhere near the disk to begin with.
Re. logging interfaces, I think you've missed the point. You want everyone to accept narrow interfaces so you can use the logger you want. You also want everyone to return wide error interfaces so you can categorize the entire universe of possible errors as you want. In the end this isn't a technical problem, it's an "I want everyone to cater for my use case" problem.
> For this it's simple to wrap them at return site in something that offers `HTTPStatus() int` and check for implementing that interface, not any concrete types, in your handler.
It's not though, the return site is inside the go stdlib. I cannot annotate it with new methods.
The only way to figure out how to translate all errors (whether to status codes or to other readable messages in localized languages) is to read the code and figure out what errors it might return.
> you want everyone to return wide error interfaces so you can categorize the entire universe of possible errors as you want. In the end this isn't a technical problem, it's an "I want everyone to cater for my use case" problem.
This is a technical problem. In Rust, libraries define error types and return "Result<T, MyErrorType>", which lets a library author decide what errors are interesting or not. If I think they have not classified an error that is useful for a caller, I can file an issue.
In java, exceptions have types, and I can know what types of checked exceptions a function might throw, and can similarly ask for more specific exceptions, or modify the library to provide them.
In go, _every_ library, due to go's error handling idioms and some mis-features of nils/type-inference, returns the most useless error type possible, the 'error' type, and I have to constantly read docs or code to figure out what types it might be.
I don't see how this isn't a technical issue with the language that, at the type-system level, it makes it an anti-pattern to return concretely typed errors in a way the type system can recognize them.
I don't agree with how you're characterizing what I'm saying as being "catering to my use-case".
Do you just never actually need to classify an error? Is it somehow weird to want to be able to provide a localized error to a user? Doesn't everyone have these problems too?
> It's not though, the return site is inside the go stdlib. I cannot annotate it with new methods.
type httpClientError struct { error }
func (err httpClientError) HTTPStatus() int { return 400 }
func (err httpClientError) Unwrap() error { return err.error } // if needed
It's not even anything special around `error`, Go's entire type scaffolding is built around doing stuff like this.
> Do you just never actually need to classify an error?
Infrequently, and virtually never for errors types I didn't write myself (other than a tiny number of sentinels like UnexpectedEOF or DeadlineExceeded).
> Is it somehow weird to want to be able to provide a localized error to a user?
Yes, it's unusual for error details (rather than e.g. outcomes) to be localized for display directly to non-technical end users. This is also true of exception messages in Java. General-propose desktop client software is rarely written in either language.
I think you're too focused on the specific issue to see my general point about interface size.
You've constructed 'httpClientError', but how do you end up using it in your program? You have "pkg/httputil" or whatever, and the methods in it return "(Response, error)", not "(Response, httpClientError)".
Even within your own program, you now have to read the code in "httputil" to understand what possible error types can be returned.
It's idiomatic to never return concrete error types, whether from the stdlib, or third party libraries, or even methods within your own program.
Even for types you do write yourself, you still have to either memorize what errors each method may return, or you have to constantly refer to docs or source code reading.
Clearly you think this is fine and go's type system is good enough for your use-cases, but every larger go program I've worked with, error handling has been painful since the errors are effectively untyped.
I assume we must have worked on different types of go projects if you haven't run into pain with this.
> Yes, it's unusual for error details (rather than e.g. outcomes) to be localized
I absolutely agree that it's outcomes which are localized, but to determine _outcomes_, you have to classify errors. If the _outcome_ is "File doesn't exist", that's a different error than "permission denied", so you need to classify. But the type you have is "error", so you have to constantly refer to docs.
As I already mentioned - Go has largely unbounded error types, not because `error` is a small interface, but because of how many interfaces get nested (a tar.Writer wrapping a gzip.Writer wrapping an hdfs.Writer etc.). If you don't like this, fine, we'll have to agree to disagree about the value of checked exceptions vs. massively leaking implementation details.
Nonetheless, Go does provide ways to check whether an error either is or can do what you want, and ways to annotate errors with logic specific to your program. An `httpClientError` is an `error`. When you get an error from a source you want to treat as a 400, you wrap it and return it, as an `error`. You use `errors.As` on it as a concrete type, or an `interface { HTTPStatus() int }`, to use the method you've added.
Regarding localization, which is a significantly different problem - the outcome is e.g. "file can't be opened". It's hard to write good error messages based on the language's error messages but this is not a Go-specific problem at all. Either you constrain your operations to the point you can bound all your error types, or you don't and report the outcome + raw message instead of trying to localize causes. And yes, this is an unusual space to be using Go or Java.
Since you mentioned Rust, we could also consider how it solves the problem - `Write` returns a `Result<usize, io::Error>` - `io::Error` has a (almost uselessly long and yet still) non-exhaustive `ErrorKind` - the last of which is `Other`, "used to construct your own Errors that do not match any ErrorKind." I.e. even in Rust's type system, they punted because otherwise you can't easily compose anything.
The main thing that irked me though is I had to spend a whole day doing a simple "take this complex object and use it as a hash key" in an idiomatic way other than just cheating and using the stringified version of the object as the key.
- Do you want to reveres codepoints, or grapheme clusters?
- Do you really want to reverse grapheme clusters, or do you want to reverse some grapheme clusters while leaving e.g. sequences of control characters in the same order?
- Do you really want to reify any of this rather than iterate backwards in the existing memory?
Yes but why? Those expressions do wildly different things both in terms of language semantics and in terms of observable behavior and most of them haul in some heavy additional machinery from the language. Perhaps where it is present, this is a case where stdlibs have implemented it because it's easy to implement, and not because it's actually useful.
(What do I mean by wildly different things?
C++: Swaps the string's contents in-place, and probably breaks any multi-byte code units unless you've got a parameterized std::string at hand.
Dart: Makes a new string but has to round-trip via an array, because... it doesn't have a string reverse? This seems like a really bad argument for your side!
Java: Reverses codepoints, but the fact you have to round-trip through a StringBuilder to handle this is also telling.
JavaScript: Same comments as Dart, but I believe this is broken, it will reverse surrogate pairs incorrectly.
PHP: Good luck figuring out what this does depending on your platform, locale, and moon phase.
Python: Another codepoint reverse, again not via strings but a lazy sequence, and also not even idiomatic - use `str[::-1]`.
Rust: And finally again... not a string reverse.
You want a Go slice reverse? You can get a perfect one post-generics.)
Not sure what you mean. The types consumed by an API are declared (though they might be interface types), and reading the godoc will give you a good overview of a package.
When would you want to look for all implementations of an interface? Is this something like an abstract syntax tree?
The interface defines the behaviour required at the point of use - that’s the point of them. You should not need to know which types implement an interface and if you do things are deeply broken in your codebase.
I’ve developed large Go codebases and never had this problem so your last sentence is false. In addition this is not an issue other go developers I’ve spoken to have ever worried or talked about.
> However, the issue this brings up about structs / types not explicitly declaring which interfaces they implement is a real and unaddressed problem, especially in large codebases. The only tool that I'm aware of that finds implementations is GoLand, at steep JetBrains prices.
So are you trying to find implemented interfaces or interfaces' implementors?
Former: In Vim I can use `:GoImplements`, which internally calls `guru` I guess.
Latter: `gopls` supports this.
I agree it's still a pain that one can not tell directly from code what interfaces a struct implements tho.
Every major editor I can think of has a way to find out what implements an interface using guru (https://github.com/golang/tools/tree/master/cmd/guru). In VSCode, it's right-click -> Find All Implementations. vim-go has :GoImplements. Using go-mode, emacs provides go-guru-implements.
> However, the issue this brings up about structs / types not explicitly declaring which interfaces they implement is a real and unaddressed problem, especially in large codebases. The only tool that I'm aware of that finds implementations is GoLand, at steep JetBrains prices.
Alan Donovan's guru tool could do this, but it kind of broke with modules and it was never updated and deprecated in favour of gopls. I don't know if gopls added this yet (I never really found a use for it).
I don't think it's very hard to write a tool for this though; parsing Go code is fairly easy and the stdlib provides a decent API for it. I think you could have a functional tool in a day if you wanted to, although without any caching it might be a little bit slow on larger code bases.
It's not great, but I use this pattern to check / enforce interface membership.
type Bar interface {
BarMethod(int, int) int
}
type Foo struct {}
// Error: Foo does not implement Bar (missing method BarMethod)
var _fooImplementsBar Bar = Foo{}
Firstly You can literally just use one of the dozens of go lsps or code tools to search for API invocations to find what structs are passed/called into it. More importantly if you need to know you've written bad code. The entire point of an interface is that you SHOULDN'T need to know the underlying type. If you do you've violated the entire point. Just pass concrete ones. I've written Go for years and never had a problem with this, even in large open source projects like Kuberenetes.
Secondly, the criticism about flipping return values order/meaning isn't a criticism of interface being structurally typed (https://en.wikipedia.org/wiki/Structural_type_system). If you return int, int and the second int "should be even", you should have defined a type "Even" and returned int, Even*. Systems which are structurally typed can demonstrate functional extensionality and (https://github.com/FStarLang/FStar/wiki/SMT-Equality-and-Ext...) and check whether you've flipped the arguments, which would be a more valid criticism (but such checks are expensive and conflict with compile time requirements). Also Java has the same problem, if you define two interfaces with the same method signature and a single class implements both you can't disambiguate.
Thirdly, the structural typing has a huge advantage, namely looser coupling and more tightly defined interfaces. If you follow the "accept interfaces return structs" go idiom, you'll see why. An open source library that does so leaves their returned structs open to be used by consumer code, that itself uses interfaces, without modification required. This means most go code has small, tightly defined interfaces, where every function on the interface is invoked in the relevant function.
For example if you have a library with this definition:
type Baz struct {}
func (b Baz) Foo(){}
func (b Baz) Bar(){}
I can use Baz in my code like so:
type Fooer interface {
Foo()
}
func DoSomething(f Fooer) {
}
And use the underlying library, while being decoupled from it, without having to modify it.
Fourthly: You can explicitly say a type implements an interface...
I don't write Golang but honestly that was one of the features that interested me the most. Automatic type compatibility. I get the criticism as you will depend on tooling to get some expected convenience. But if you are used to void *ptr anyway...
To be fair, most APIs need documentation and code is just plainly not enough. At least if we are talking about specialist interfaces that aren't just another web framework.
> ... on August 16, 1999 that [Lars Knoll] had checked in what amounted to a complete rewrite of the KHTML library—changing KHTML to use the standard W3C DOM as its internal document representation. https://en.wikipedia.org/wiki/KHTML#Re-write_and_improvement
> In March 1998, Netscape released most of the code base for its popular Netscape Communicator suite under an open source license. The name of the application developed from this would be Mozilla, coordinated by the newly created Mozilla Organization https://en.wikipedia.org/wiki/Mozilla_Application_Suite#Hist...
Netscape Communicator (or Netscape 4) was released in 1997, so If we are tracing lineage, I'd say Firefox has a 2 year head start.
Isn't it sad that he has to type out his only messages to the world letter by letter, and he spends his time typing out the names of mega-brands?
"...‘(son’s name) moechtest du mit mir disneys die hexe und der zauberer anschauen auf amazon’ – ‘would you like to watch Disney’s witch and wizard with me on amazon’ on day 461"
He's talking to his kid. Joe Average isn't going to tell his son that he has plans to use the BCI to transcend this mortal coil and claim the power of God. He's going to do what this guy did -- ask for a beer, to hear some of his favorite music again, and to enjoy something simple with his kid that doesn't require a lot of physical input or talking from him.
I essentially paid my way through college by turning SMB's spreadsheets into CRUD webapps + some tiny reporting. There is a huge, huge market for this if you wanted to trade some of the time you would spend writing code with marketing, cold calls, chasing down clients for invoicing, and other non-tech stuff.
Removing a top level domain (TLD) from the DNS when people still want to use it is a no-no. There's a vibrant, active community in .su, and I hope they continue.
It's mostly completely distinct from the political question "what does it mean" regarding 2 letter top level domains, and the ISO3166 list, and the status of entities in the ICANN process. (well.. maybe not the last bit: ICANN has enough fights on its hands without trying to reclaim some namespace territory)
I agree that the use of ccTLDs by people who are not from a given country is OK - like having a .it or .me or a .tv domain as an American or a Brit etc. However the specific case of .io is, to put it politely, rather complicated.
Sure. Tuvalu made good income from .tv, There's a vibrant market in ideas out there. It's just a bit odd that it existed as a grandfathered in thing, And then the grandfathering remained after the raison d'etre ended.
Haha I love how most of the internet just agrees that tokelau is like the outcast TLD of the internet. I've seen filters alert just from accessing a .tk because of them being free and maybe still are. I think it used to be Dot.tk giving them away
As useless and pithy it is to say "just restore from backup", having your livelihood (or a significant time investment) depend on a system far outside of your control, where you have no service guarantees or even a billable relationship, is a fairly shaky ground to stand on. Ultimately if you spend your time producing digital assets, you should have taken action to ensure you had ownership and control over them somewhere.
Please don't scold someone who's already in a shitty situation, or lecture them with the obvious. That breaks the HN guidelines, notably this one: "Be kind."
It's extremely easy to do this kind of thing on the internet and not as easy to realize the effect it has on people, and also on the community.
Many people have a naive trust of free services. If your livelyhood/business depends on uploaded files, do not trust Facebook, Youtube, Gmail, Google docs, etc to store it forever.
I think it's important to mention that such trust is misplaced and risky, ALWAYS make backups. Sure it's generally common sense for many, but the OPs story is a nice example.
I hope she can recover those videos. Aside from not backing up initially, I’m also wondering why or if she did anything after getting those 3 strike warnings :$
Things like this happen, get escalated to the media, and it creates public awareness of the risks of hosting digital content only in the cloud on servers that you don't own and don't even pay for.
In other words, the next generation of normies will probably understand this because of people before them learning the hard way.
It's not so much about any longstanding personal policy, but if your dog of 10+ years had just died recently, and you sat down to watch a movie to relax, you might not want the movie to feature a prominent animal death, for example.