From what I've seen, the people who complain about go's design are people who are more concerned about the ways in which it is not correct (by some definition) and less concerned about just getting stuff done.
I don't "like" go (or any other programming language), but I'm able to get more done in it in a shorter amount of time than any other language, the created thing consumes tiny amounts of resources, and most importantly when I _or anyone else_ goes back to change something weeks, months, years later it's easy to re-establish or gain contextual understanding.
These were the first lines of Go I ever wrote 15 minutes ago, as a response to the claim that Go had working enums. This is the kind of thing that makes me itch.
https://go.dev/play/p/MMPMh7_U81-
I think "being simple" doesn't necessarily mean "must have subtle sharp edges and papercuts everywhere". Just like javascript I think it falls into a pit of being superficially "low complexity" or "simple", but all the subtle gotchas and unhelpful tooling (The fact a compiler can't help me realize I had added an entry to the enum, but forgotten to update a name list just means the whole feature is no better than just plain ints that we had in C since before I was born).
I like go, and I use it to get stuff done. I'd be able to get stuff even more done with sum types and pattern matching and better generics and iterator tools and it's a shame Go doesn't have these things.
I mean everything you just said about Go applies to Python except the "consumes tiny amounts of resources"--it's certainly my most productive language, and the code looks a lot like the pseudocode people write when they're trying to descrbe an algorithm so it's pretty dang easy to read. But you don't hear me going around claiming it's well-designed. Taking async design cues from f-ing JavaScript, leaning harder into the GIL, was a horrific mistake, for example.
The framework is complex, not its use. It’s actually extremely easy to use. If a project builds a framework that tries to cover every case in an opinionated way, they’re going to end up with a complex framework. Why should the fact that the framework externalises most complexities mean that it shouldn’t be used?
I'm always confused by these sorts of posts because they happen often so there is clearly a problem but for some reason I've never had much of an issue. I've been using and developing with Python for about 15 years. In that time I've worked on Python projects large (OpenStack) and small (gabbi) and taken over maintenance for some old standbys (wsgi-intercept, paste to name two). Dealt with the 2->3 transition. Released a whole bunch of things to PyPI and relied on far more things that I've pip installed from there. It's been fine.
So there's a few types of projects you can write in Python:
1. Server applications that run in a dedicated environment.
2. Tools you write and run just on your machine (or some virtualenv, whatever).
3. Redistributable cli or desktop applications which end users will install and use.
For the first two types, you should never have any issues with Python and its dependency situation. You pin everything, and that's it.
For the third kind tho, it's complete pain. Different distros ship different Python versions, so you need to support all of them. You also have to consider that dependencies can't be an EXACT version, you have to support a range of them, and a variety of combinations.
And then, one dependency has a version that works in Python3.6, and another for 3.9. But they had an API change, so which one do you use? It'll break for half your users either way. Of maybe just put some `if version <= 3.6` all over the place, like we did during the py2->py3 transition?
#3 is the exact case where you also want to just pin everything. For an end-user desktop application, you ship a properly tested bundle, instead of trying to support all the different versions; as the end-user (unlike a developer using a lib on their own machine) should not ever have to interpret compatibility issues and should get a package that's been tested to work as a whole.
If a distro ships python 3.6 and the app wants to use 3.7, then the end result must include python 3.7 as well, either by distro being capable of having both versions at the same time or the app needs to ignore the distro-python and ship its own version in the package.
If an entity makes profit off the back of my labour without compensation a reasonable case could be made that harm has been done to me.
Or at least a labourer may legitimately claim they wish to share "freely" only to some. And they can also choose to change their mind on any subsequent work.
This is especially the case when the entities involved are corporate, not individual humans.
I think this is where I disagree. I'm all for identifying corporate exploitation of free software, but this isn't it. If I work to enrich the commons, and as a result someone profits, I don't think harm has been done to me. Sure, it might feel bad to know that someone is profiting because of my work and they couldn't spare anything for me, but ultimately, I didn't expect to make any money when I did the work. I would have done it anyway. It's really hard to see how I've been harmed here.
You can make that case, and you're entitled to distribute your software under terms that prevent this.
But this is the deal you sign up for when you make free and open source software. If you want to make another kind of software, that's quite fine, but it's not free software nor open source.
Especially if your complaint is "We got lots of growth because people adopted our open source software but then Amazon published a hosted version and now we can't claim as much of the commercial opportunity, so we need a more restrictive license."
Would the software have attained the userbase it did if they were the terms from the outset? A lot of these companies just assume that it would have been the exact same except for the absence of an amazon competitor if these licenses were used.
It's great to see more and more API testing tools that use a format intending to be readable.
I personally think YAML is a bit more readable for humans so that's what I used when I created gabbi. Here's a similar test to one of the examples from apitest:
Agree. I wasn't at all convinced by the examples showing the Echo was somehow better than using the "built in" signatures, especially since there's quite a bit of handling that Echo (and things like it) makes implicit that you'll probably want to be explicit in some edge case.
Coming from WSGI, I found go's middlwares familiar and positively pleasant.
I too ended up on Chi as the router that worked well without getting in the way.
Anybody else get bummed out that many times that we create a lightweight thing to compensate for something overcooked (like XML) the new thing eventually ends up overcooked in much the same way?
In all fairness, JSON itself continues to be as simple a format as it ever was. Having schemas is an important adjuct because it frees devs up from constantly translating specs into ad-hoc validation routines that all too often miss something or make mistakes. Validation up front saves a tremendous amount of pain dealing with a key error deep in a call stack when the moment a config file was read its omissions or mistakes could have been identified.
Moreover, and on a related note, in many ways, JSON is great as an exchange format, but stifling as a config language. There is a lot if room between JSON and XML to work with.
> In all fairness, JSON itself continues to be as simple a format as it ever was. Having schemas is an important adjuct because it frees devs up from constantly translating specs into ad-hoc validation routines that all too often miss something or make mistakes. Validation up front saves a tremendous amount of pain dealing with a key error deep in a call stack when the moment a config file was read its omissions or mistakes could have been identified.
I agree. JSON is overall better than XML for most things. It's simple and universal. This simplicity translates to the new incarnations of some good ideas that people were trying to implement on top of XML, like schemas. They are not mandatory, but useful in certain domains. Simpler format means that these things can also become simpler. So eventually we may do them right. It's a process of evolution.
> Moreover, and on a related note, in many ways, JSON is great as an exchange format, but stifling as a config language. There is a lot if room between JSON and XML to work with.
Also agree. There is also a tiny bit of room below JSON and above unstructured text that can fit a universal syntax on top of which other formats can be built, including ones for configuration. A modular one. Where you can have different formats that share the same underlying syntactical structure and as much idioms within that as reasonable.
And here comes the pitch: this is what I'm trying to introduce. A simple universal syntax. It is still somewhat undercooked (less the syntax which is minimal and stable but more its description and formats on top of it), but might be interesting for certain people. The thing is called TAO and it has a website here: https://www.tree-annotation.org/
I hope somebody will find this inspiring at least.
`raw` is more of a type annotation than operator. You can also impose an implicit interpretation of (some of) your data as raw, without a type annotation.
One of the best representations of the 'simpleness' is the way you can draw it in a graphical loop diagram as they do on the json.org site.
When you can make your 'format' in to a not-too-big diagram like that it makes it far easier for anyone interested to 'get it' and encompass the whole thing in their mind to work with.
SQLite is the place that (to my knowledge) was the first to do these "railroad diagrams". Here are all of theirs (though they're also available inside the documentation): https://sqlite.org/syntaxdiagrams.html
Definitely not the first, I see that the first release of SQLite was 2000, and I found these railroad diagrams in old Pascal programming books of my father.
It's because it was easy to use, and so people adopted it long before realizing just how many features they needed that it doesn't provide (for example, lack of types). "Simplicity" is a double-edged sword because you can't actually eliminate natural complexity; you can only move it around into (hopefully) more convenient / less chaotic forms.
A huge improvement over JSON, but you still implement Tony Hoare's billion dollar mistake! There also appear to be no schemas / static types or sum types (the dual to records)? A schema would allow to you to overload the string literal, rather than require all those prefixes.
A data-exchange format is essentially developing a mini-language. Even if we prohibit abstraction, we still want rich static types and the ability to define new types (algebraic types, nominal types). Taking inspiration from programming language theory, will hopefully help avoid a result like Google Protobufs, which is awkward, ad-hoc and non-compositional.
Null is in there because it exists in the real world (unfortunately). There's no putting the genie back in the bottle (although there's an admonition against using it in the spec). Pretending it doesn't exist would cause more trouble in the real world than letting it be.
The string-type prefixing is there so that you don't actually need a schema for 80% of use cases (schemaless data is usually enough). A schema can be added later if desired, and I've been thinking of what that might look like, but it's at a different level than the encoding format and can be developed independently.
The primary purpose of this format is to serve the 80% use case (general purpose, ad-hoc, hierarchical, schemaless data with fundamental type support - or something that easily fits within this paradigm). For the remaining more complicated 20%, there are custom types and at some point in the future, schemas.
> Pretending it doesn't exist would cause more trouble in the real world than letting it be
I don't agree at all with this point. RDBMS types for example are non-nullable by default. Protobufs, XML and many other exchange formats also have optional types but not null added to every type. If you want better interoperability with programming languages, I think it would be better to go after e.g. IEE754 support.
The default nullability of RDBMS types is implementation-specific. Protobufs requires a lot of ugly workarounds for languages such as Java to handle the language's nullable types. You can't eliminate the complexity; only move it, and protobufs moved it in a way that punishes languages with nullable types. XML at least works via omission, but that doesn't handle the case of explicitly signalling "no data", which is a valid signal in many languages.
These schema are just applied uses of JSON and not modifications.
But XML was perverted due to its inherent extensibility, The JSON syntax hasn't changed: scalars, arrays, associative arrays. That's all! So it has remained "pure" so to speak.
Fortunately the only issue I've run into with JSON is lack of proper NAN and NULL support, but that is largely a limitation of the language's implementation (can't support NULL if you ain't got a NULL!).
Yes, it has null, but when you parse it with, say, Boost::property_tree, null is 0, which is not true null because there is no true null in C++. Language limitation.
Cool link, btw. For all the years I've been using JSON I never visited the main page!
nullptr isn't "null", it's a null POINTER. In languages with a NULL type, and variable can be a NULL. E.g., in python you can say "x = null; x = 1;" in C++ you cannot say "int i = nullptr".
The point is not to "escape" complexity, but to manage it.
Of course, these type of "I hate the word simple" comments are always besides the point. They could be the whines of frustrated, incompetent programmers who continually produce overly complex solutions to relatively simple problems and call it a day. We all know those programmers exist.
In a way it is a side-effect of attempting to bolt the same abstractions the 'old and complicated' system had on top of the 'new and lightweight' which essentially takes the problems of old and puts them back on top of the simple stuff.
Sometimes it doesn't happen like that, i.e. the whole clang-ir-llvm thing, but it often does (mostly during serialisation and API exports for third party consumption).
Take WSDL and XSD as an example, the idea was that you put your details in a file that can build on other abstractions and the result is a universal and portable format that allows any system to work with any other system. That failed of course because you end up exporting implementation details inside of those 'portable' abstracted specifications making it no longer portable because you now have to implement the exact same details on the 'consumer' side as well.
Comparable things happen with Protobuf and GRPC due to the same reasons. It's not as bad (yet) due to limitations on data formats you are allowed inside the protocol, and it makes it a bit more an RPC with message passing rather than a complete API encapsulation. If the maintainers can prevent it from eating in to serialisation of arbitrary objects it might even not end up all that bad after all. But that was the theory with XML as well and we all know how that worked out.
To me it doesn't seem like we are going back and forth. Rather that we are moving forward in a zig-zag pattern. One win is cultural.
In XML-world, you felt this shame when you weren't use schema. You didn't have to, but you really ought to kind of deal. Now it's instead "hey there are schemas if you want that tool". To me that's progress.
They made the same poor choice as the designers of XML schema, which is to use the target language itself to describe the schemas. That is, a JSON Schema is written in JSON. As a result, they're extremely verbose and tedious to work with.
If you contrast JSON Schema with the type declaration subset of TypeScript, you'll find that the latter is much more concise and readable.
Having said that, there's an interesting discussion to be had about the distinction (if any) between schemas as understood in the database/XML/JSON world and types used in programming languages. JSON Schema does more than most programming language type systems do (e.g. requiring string lengths/numbers be within a certain range) and this is useful for validation. It still doesn't excuse the syntax though.
It's technically possible to devise an alternative syntax and a bidirectional converter between it and the json jsonschema syntax. potentially the current json syntax could become some sort of "intermediate representation" not meant for direct human consumption but still useful to simplify implementation of tools that generate or interpret schemas (which wouldn't need a full fledged parser)
A quick web search didn't yield any existing project attempting to do so, but perhaps I'm not typing the right keywords. Does anybody know if this exists?
If not, would you like it? What would be the main characteristics such a syntax should have? (Mine pet peeve are comments, i.e. lack thereof in json)
I am building one, but it just started. Turns out we can even implement module system on json scchema. It's going to be convention/opinion based output; a subset of how a thing is described in jsonschema e.g. tagged union.
Jsonschema is a mixed bag of structure and validation, that sounds simplified, but its expressive power comes from the mix. For example, I have to limit the use of "Applicator" keyword (oneOf, allOf, anyOf) only under my controlled keywords under $defs .. urggg.
I think there's an argument to be made that validation should be done with a turing complete language to be most effective. However, JSON schema, while weaker and more verbose does have the advantage of programming language independence which whatever typescript has absolutely does not.
Either way JSON schema is fairly lightweight and didn't try to accidentally create an awful new programming language (cough XSLT cough). I don't see it as indicative of any of the kind of fuck ups XML went through.
It was a great choice for XML... I've used XSLT to transform schemas into code many times.... (related: XSLT is more readable than JSON equivalent 'jq')
I don't "like" go (or any other programming language), but I'm able to get more done in it in a shorter amount of time than any other language, the created thing consumes tiny amounts of resources, and most importantly when I _or anyone else_ goes back to change something weeks, months, years later it's easy to re-establish or gain contextual understanding.