The melting pot of JavaScript (2017)
increment.com
increment.com
Java, C#, Rails, and to some extent Python are much saner choices. The massive churn of the JS ecosystem bleeds through to the backend, hard.
JS could use a little more of the cruft and process that makes Java and C# especially so "uninteresting".
Java especially is kind of a joy to work in if you ignore the cruft. Everything is generally well documented, the libraries are mostly very solid, code is almost always backwards compatible, there isn't a zillion ways to do everything, frameworks tend to live for a decade or so.
And it's faster than JS, and uses way less memory, and mostly solved dependency hell and bloat over a decade ago.
Java feels like it was designed, not grown. Everything follows similar convention so it's easy to pick up new libraries. The advantages are many. The drawbacks are few as long as you use things like Lombok and code generation liberally. By the way; code generation using agents, annotation processors, and bytecode manipulation is pretty much standard and a godsend for doing interesting things (and getting around the cruft) .
In java, I can write code on the fly at runtime, or even during compile time using standard tools. Js barely even supports reflection. This is a huge underrated shortcoming of js if you're doing anything complicated
Python not as scalable, Rails is stagnating, the ecosystem doesn't evolve anymore/dying, doesn't play well with SPAs, C# weak to none ecosystem outside of Windows and devs earn a fraction, Java verbose and dev productivity subpar (there was a reason people came up with Scala), Java devs also suffer lower salaries
If you reach out to the Java ecosystem you can find libraries, frameworks, and language extensions that make it relatively easy to code in. For example, with Lombok you don't have to write any getters and setters, or catch checked exceptions. Java 11 also makes good improvements to lamdas making method chaining a lot nicer. The Java I write at work is barely more verbose than the TypeScript, maybe 15% more code to do the same thing.
Java devs also get paid really well honestly, pretty sure it's better than the pay for JS and Python actually.
Not scalable in what way? Every aspect of scalable that I can think of is in no way limited by choosing python as your language.
Mayne that is your problem. Try new stuff. V8 is still one of the fastest and most optimized VMs.
Huh? Rails ships with built-in, no-config webpack support (https://github.com/rails/webpacker#installation) as well as install tasks for the most-popular front-end solutions (https://github.com/rails/webpacker#integrations)
Can you explain what Java offers with regard to reflection that JS doesn't?
My feeling is that reflection is almost moot in JS since you can inspect/mutate objects at runtime however you like. But maybe I'm missing the point of reflection.
There is a Reflect object with a bunch of static methods on it in ES6. It mostly just replicates functonality that already exists in the language, and my suspicion is that it's mainly there so it can be extended at a later date without breaking backwards compatiblity.
Maybe I'm just complaining that JS is too dynamic, but being able to generate code at compile time with reflection and know it will generally work (type checked) is nice.
Tip: in JS, I don't want OOP class. If you really want class, could you show me the intention behind it?
Adding another example, JPA MetaModel generator that allows you to make strongly typed calls in ORM.
Basically, it let's you generate code at compile time that's seamlessly integrated into the existing code. So it's generated code that still gives you IDE autocomplete support etc.
I automagically map some postgres JSONB columns to a parsed object form. Looks just like a regular typed nested object.
You basically HAVE to do this in Java otherwise your program won't work. In JS, you can look everything over at runtime and dispatch from there (made much easier because first-class functions and closures are a thing).
Correct, that's what you have to do in dynamic languages - look at what came in from the database and manually validate+convert it into the format you actually want. Also with pretty much every other form of input (JSON bodies, form posts, queue messages, etc). It's a lot of tedium.
When working with node/python/ruby, I often find myself wishing I could just declare a type and be assured that "the system" will get it right instead of me having to code it out myself. You know, like Java.
Well-written Java programs are generally more concise and less verbose than well-written JS/Python/Ruby programs. Which is to say, when programmers actually validate input instead of (ahem node) crashing the process and dropping all inflight connections when someone submits a json body missing an expected field.
BTW absolutely nothing prevents you from building Java apps by declaring everything as Map<String, Object>. Nobody does that because it's a horrible way to program.
This isn't at all true. I can say this from experience using statically typed Python extensively, in an average code base, 80% of your functions, if not more, are already statically correct in Python, one just need add an annotation. Then you're just as "well written" as the Java.
With or without the annotations, the code is still just as "correct".
> BTW absolutely nothing prevents you from building Java apps by declaring everything as Map<String, Object>. Nobody does that because it's a horrible way to program
Yes, but only because you'd need to explicitly cast things everywhere and write out declarations everywhere. If you could always elide casts and type defs, it becomes a lot less horrible.
> Correct, that's what you have to do in dynamic languages - look at what came in from the database and manually validate+convert it into the format you actually want.
You still have to do this in static languages. Maybe a library does it for you, and it gives your an error or something you know is a DbRecordFieldStream or whatever, but dynamic languages can do the same thing. Orms validate input in dynamic languages too. Rails and Django can validate request formats. Protobufs work in every language.
Well I guess we'll just have to disagree there. I spend a lot of time writing code in all of these languages. By the time you've bulletproofed your dynamic code, you've got more code than if you'd just declared a simple static Java type.
I can define this...
@Data
public class Thing {
final String text;
final Instant when;
}
@Path("/thing")
public class ThingResource {
@POST
public void doSomething(final Thing thing) {
// ...blah
}
}
...and stop worrying in my implementation about what was actually passed in, or how a JSON string date got turned into a real date representation. This is mostly-vanilla Java.Sure you can, with enough extra code and clever libraries, hack together a crude typing system into dynamic languages to automate much of the conversion. At the end of the day you're still declaring types, and it doesn't end up being as elegant as having the type system built into the language.
No, its Java EE, which like I said, has an entire library devoted to safe marshalling[1]. Marshmallow does the same thing for you in python. Java EE including a marshalling library has nothing to do with static typing.
This is python + flask + marshmallow (2 very common web libraries)+ a 2 line helper function:
@dataclass
class Thing():
text: str
when: datetime.datetime
@app.route('/thing', methods=['POST'])
def handle():
thing = unmarshall(Thing, request.form)
# blah
Or, like I said, use protos, where this would be something like from thingproto import Thing, ThingService, ThingResponse
class ThingServiceHandler(ThingService):
def HandleThing(request: Thing, response: ThingResponse):
# blah
and everything is validated.[1]: https://dennis-xlc.gitbooks.io/restful-java-with-jax-rs-2-0-...
Dragging protobufs into this is weird too; you've ignored the IDL and build infrastructure required to set that up, and in any case that's specific to when you're working with protobuf APIs.
I'll go back to my earlier point, which I think you've illustrated fairly well, which is that well-written Java code tends to be more concise and less verbose than Python (and friends). Our two examples are nearly identical in terms of meaningful lines of code, but in the Python example you have to ask for marshaling.
I'll also point out that flask (which I use myself for python webapps) handlers are forced to interact with flask-specific objects and therefore are obnoxious to test; the JAX-RS example is pure program logic and can be tested as vanilla Java code. This is one of the big advantages of moving marshaling "out" of your program code.
That's only an API wart. It'd be possible to elide that pretty easily if someone wanted to write a library to do that.
I could write a library function or flask extension or whatnot that resulted in
@app.myroute('thing', method=['POST')
def handle(thing: Thing):
# work with thing
and the unmarshalling is handled by the decorator and type annotation. Your prime example of java being less verbose is a wash. They're at best equally verbose, and you picked something that java has libraries specifically catered toward.>I'll also point out that flask (which I use myself for python webapps) handlers are forced to interact with flask-specific objects and therefore are obnoxious to test
Huh? Here's an example of a test from the flask docs[0] that makes a request and checks the result.
def test_empty_db(client):
rv = client.get('/')
assert b'No entries here so far' in rv.data
Its a simple example, but having written tests for flask myself1. There should be minimal logic in the handler. You should defer most logic to a library function, you can also not use the decorator form and instead declare `app.route('/path')(function)` and just test function itself.
2. Even testing the handlers and doing end to end stuff with a running server isn't that hard. I'm not sure what you're experience was, but my guess is you weren't leveraging existing libraries.
>This is one of the big advantages of moving marshaling "out" of your program code.
Here's the implementation of that:
def myroute(self, *args, **kwargs):
def wrapper(f):
@self.route(*args, **kwargs)
def new_route(*args):
arg, schema = f.__annotations__.items()
parsed = schema.load(request.form)
return f(arg=parsed)
return new_route
return wrapper
And now if you've tested that, you no longer need to worry about marshalling in your program code.Flask however is relatively generic, it can handle things that your java examples can't, like an endpoint where you don't know the schema, which might happen if you're doing something like hosting a user-provided function or something of that nature (I implemented an AWS-lambda style thing in a hackathon with that). Something like
@route('/user_endpoint')
def handle():
return convert_to_html_response(user_function(**request.form))
This was really easy to implement. I doubt it would have been as concise in Java (and note that you are leaving validation to the user here, so none needs to be done by you).Flask lets you do that. If you want to restrict yourself to schematized requests, you have more information and can make more assumptions, but flask isn't a REST framework, its a generic web framework. If you want to restrict yourself to something with known schemas, you can do that pretty concisely[1], even when dealing with relatively complex marshalling (and you can do it outside of your logical code under test via decorators).
[0]: http://flask.pocoo.org/docs/1.0/testing/
[1]: https://flask-restful.readthedocs.io/en/0.3.6/fields.html
@POST
public void doSomething(final Map<String, Object> thing) { ... }
So please stop trying to explain to me all the things that Java can't do concisely.Also you kinda missed my point about unit tests. Your test requires specialized flask-oriented objects (client, rv). Tests of the Java doSomething() can be written entirely without knowledge of the container; doSomething() is pure program logic. And the methods support refactoring.
you picked something that java has libraries specifically catered toward
I picked a basic REST service. I'd call that a pretty common use case.
There should be minimal logic in the handler. You should defer most logic to a library function
Again illustrating my point that well-written Java is more concise. You don't need to do this! The Java "handlers" I've shown are pure logic. There is no point in wrapping it with another layer.
Sure, you probably could build a webapp framework that makes Python a lot more like Java. But so far nobody's done that. So Python programmers write wordy verbose flask apps with tons of validation and marshaling logic. It's tragic.
More verbose than the Python.
>Sure, you probably could build a webapp framework that makes Python a lot more like Java
Not could, did. Literally just did, in 10 lines of code. Or there's flask-rest, which I linked.
>Again illustrating my point that well-written Java is more concise. You don't need to do this! The Java "handlers" I've shown are pure logic.
And flask-rest does that! If you're writing a restful service the more concise, better specialized tooling is readily available.
Now write the unmarshalling code and tell me Java is still more concise.
var results = (await sql.query`
...
`).recordsets[0].map(rowToObject);
It's really easy... no need for complicated ORM/ODM tooling at all.As far as the size... create a docker container from node:10-alpine to run a given node application, and create a similar container with any application running full Java. And compare the final size.
I've never heard anyone server-side care about the size of a deployable. It's the size of the codebase that's an issue. Tedious conversion code does not work in javascript's favor.
Looks like it works by having the typescript compiler generate experimental annotations in the output javascript, and reading it using a polyfill for the proposed ES7 reflection api. On one hand, yeay looks like proper runtime reflection is coming! On the other hand, it doesn't sound fully baked yet... <insert here a general grumble about how everything in the JS ecosystem is in this state>
Among hundreds of other things, getting the return type of a method and getting the input parameter names (+ types) in a way that doesn't revolve around literally parsing the functions toString() representation.
Oh, and typeof checking that isn't disgustingly broken.
Ah, that's quite cool.
Which in some ways is a good thing as you can do a lot more optimizations.
Type information literally doesn't exist at runtime, though. Isn't it kind of ridiculous to compare languages like that?
To draw out that analogy... we live in Greenland. Cars with skis are surprisingly useful.
Correct if I'm wrong, not all types get erased in Java. Doesn't type erasure only happen for generics? Say I have a non generic, plain Java class and want to inspect one of it's method's return types at runtime to see if it returns class A or class B. I can do that, right?
It's actually WAY easier than with C# or Java. Since the use-case of reflection itself is largely unnecessary.
There's no way to hook into the loading of modules in a standard way - you have to know how the modules are compiled and required.
router.get('/users/:id', (id: UUID) => ...)
router.get('/products/:id', (id: Int) => ...) router.get('/users/:id'. skipNonUuid(id => ...))
You simply have a function/middleware that does the check.... or `compose(skipNonUuid, dbo.findUserById, ui.formatView('modelName'))`You can do function composition that is nearly as simple and far more flexible in general with JS
One thing comes to mind, how to twinkle stuff inside closures?
At least, that is how I find it, my productivity shoots up when I don't have to be moving between two imperative languages that most likely share a lot of their syntactical DNA with C but each have their own fun little differences.
I guess you could hire less proficient engineers which is a sell for startups, but I don't think it's worth the downsides of the current js ecosystem
I have mixed feelings about this. I don't feel comfortable with assuming that just because I use the same library in backend and frontend, I don't have to ensure consistency and behaviour. But then again, I've used this approach in one ClojureScript project (ClojureScript can transpile a lot of Clojure libraries to JS), and it is convenient.
And don't associate less proficient engineers with Javascript dude !
And that is only when not using JSF, Spring, Forms, MVC, Liferay, Sitecore, which generate the JavaScript validators automatically from type annotations anyway.
For my projects, the Web layer is only the View part of MVC.
Aside from form validation I find I might have a number of utility functions that are used on both layers.
I find there are a few other edge cases, but those are the most common situations where reuse is nice (on the other hand what I often do for personal projects is just build the server side and client side code from a gulp pipeline and not worry about needing 'isomorphic' code reuse, but often teams on paid for projects find this approach confusing)
Since ES6 it's even better.
Just choose the best programming language, and everyone can learn it; and they'll be happy and grateful in the long run that they chose to learn this new language, rather than use whatever they were familiar with.
Moreover, Java is such a simple and an easy language to pick up. If the cruft is too much to deal with, go with Kotlin. An experienced developer could learn either language (Java or Kotlin) easily over a single weekend.
Also, it's easy to learn a language's syntax over a weekend, but it generally takes a lot longer to start being productive and writing idiomatic code in a new language, especially if you're also learning a new platform. That's time that you or your team may not have.
Oh god...
Yeah, no. None of this stuff is a substitute for actual code quality. Give me a good engineer that refuses to write tests over a mediocre one that does TDD any day.
There's always a trade off.
CRUD apps generally go into production, unless something goes horribly wrong.
Linters: ErrorProne Checkstyle PMD SpotBugs Nullaway
All with highly customized settings
All warnings enabled on javac
Google-java-format to autoformat everything on build.
For runtime analysis: LeakCanary to find memory leaks
Hibernate with interceptors to find long queries
Rest framework or gRPC with interceptors for long calls
Proxied JDBC connector to find long or N+1 queries
Opentracing/Zipkin integration to make debugging crazy stuff easier
NewRelic for projects where the $ makes sense
And I'm always on the lookout for more of these tools. In the long-run they save enormous amounts of time by preventing buggy code and keeping most shitty hacks out of the codebase.
Unlike tests, they don't break constantly and add more maintenance burden to the codebase. And it's less work, one time setup vs ~50% codebase bloat to add tests.
I see project leads call for more tests all the time to "fix" an unreliable codebase where there's zero linting. It won't save you from everything but I swear it's like 95% bug reduction. You should have most/all of these tools in place before you consider writing the first tests
No, you can't.
In fact, I can't even begin to see how "apply this specific standard to the code" (linting) is even remotely related to "know everything about this particular domain so you don't make any mistakes in creating an application for it" or "know everything about this particular system so that a given difference in configuration screws up your application at run time".
You seem to be primarily a java developer so I understand why you prefer avoiding tests (among the many things that Java makes absurdly difficult, writing tests is one of them) but you should still write tests .
Look at any serious open source project, most of them have hundreds, thousands of tests. It's almost presumptuous to think that one knows more than the community.
> I swear it's like 95% bug reduction.
The only situation where linting really causes that much of an impact, that I've seen, is in an application where a huge portion of the code was just connecting or boilerplate that should've been brought from third party libraries anyway, and was written only because of the NIH syndrome.
Mind you, having code style is necessary so that any given developer can quickly get up to speed and more easily review other developer's code, but it doesn't (nor it shouldn't) tell you whether whatever you wrote actually works.
Assuming otherwise is like pretending that a movie featuring state of the art special effects, cinematography, etc, isn't still Transformers or similar garbage.
For the average crud app, if you're wrong about the requirements the tests will be wrong anyways. It sounds like you're talking more about TDD which IMO is a cargo cult. And I'm hardly the only one with that opinion. Integration tests are important but that's more about running data through the code all at once than testing each function in isolation.
Also, many open source projects get along with hardly any tests. The Linux kernel is probably the best example, but there's tons of popular projects without good or any tests. Check NPM popular repositories, I'll bet you more than half of the top 500 are under 10% code coverage. Tons of huge apps are doing fine without tests, and many I've worked on with tests are still horrible.
I haven't really noticed any contribution from having lots of tests. IMO what's far more important is linting and maintaining code standards. It's hard to write a function that's horrible to debug when the linter limits you to 300 lines. Or a class that's totally incomprehensibly long when the linter limits you to 1000. All of my debugging nightmare projects have been due to lack of sound OOP principles, huge files of spaghetti. Good linting prevents that from happening.
Besides Java my other big language is TypeScript. Using Mockito in java isn't that bad, and JUnit5 or TestNg are decent. Certainly easier than getting tests working in the garbage fire that is Angular6 + Jasmine + Karma.
But TDD is about neither, it's about test-first approach at the unit test level, which is arguably less useful and leads to design by random walk.
You might be surprised how much bad logic static analyzers can catch though.
Compared to when I'd have to use ActionScript, JavaScript, VBScript, VB6, T-SQL daily... that was sometimes painful... then adding C# and VB.Net to the mix was ugly having to switch from one area of code to another.
[1] Whoever came up with isomorphic really liked their fancy math terms. Personally I'd have chosen automorphic, as it's all contained inside JS.
There is something precious to being able to do more with substantially less code, which is why I avoid OOP all together. You can't do that in Java.
Though Java was 'designed', it was not 'designed' to be an http/web server.
JS, particularly Node.js has really adapted itself to that well.
And one small but massive difference: JSON is how data is passed and it fits seamlessly into Javascript, and doing JSON in Java is an ugly, ugly thing.
As soon as you compare not JS/Java, but Java/Tomcat vs. JS/NodeJS - then you get a different comparison.
I quite like using Typescript on Node.js over Java - development speed is faster, and this is a really important thing.
https://en.wikipedia.org/wiki/Billion_laughs_attack
It got me thinking about it. JSON is annoyingly simple at times, yes. But that also protects it from some pretty gnarly stuff seen in XML and YAML. I suspect it's a considerable contributor as to why it's the choice transport format.
I wouldn't toss it in with XML just yet.
It is only a matter of browsers getting native support for gRPC.
With gPRC there's still a lot of binding code, and you need to map all of that in Java, but you do get some validation etc. out of it. It does make the 'data transfer' comparison a little less harsh.
It's a very specific technology, and as long as it can be implemented fairly efficiently 'up the stack' in JS, then it mostly belongs there. Aside from HTTP2 (which is a roadblock now, but not soon) it'll be fine in JS.
But yeah json is much nicer in JS generally
Why do you think so? Jackson and Gson work very well. Serialising and deserialising from/to POJO/JSON is trivial with them.
In Java, you have to abstract the document and write a lot of code to access, add, remove things etc. - or - because there is no such thing as an untyped POJO in java, you have to set up a ton of things if you want to use real objects.
You could also use a POJO for the fields you know and put a map inside for the fields you don't know.
If that's not enough you can use JsonNode, or ObjectNode where you can freely add and remove json values.
First time I hear options are bad. Many options and competition lead to best products. There are enough posts and people who tell you what you should use.
Or just use npmtrends or npmcharts. 1 second later you know what is going on and what module you should pick.
Why are people criticizing something they have never used?
While I agree the package management in JS could have been better, most other too-much-config problem is just because of the variety of problems and the variety of potential solutions.
And anyways, there's the entire backend JS ecosystem, which is extremely behind Rails in developer ergonomics. I can spin up a REST API in Rails in half the time it takes to connect Node to a database.
You also confusing matters. You need Webpack, Babel etc for the frontend not the backend. And even in the frontend it got abstracted away by things like creat-react-app. So you shouldn't them see them too often.
I do think create-react-app is a good innovation in the JS world. However, I've never found a good equivalent on the back end. Setting up even the most basic CRUD REST API requires a whole lot of typing for very little reward.
As for convention, I think JS could do with more of it. I find that when I talk about adding more convention, people take it quite literally as "we need to reinvent Rails in JS". That's not at all what I mean. Convention can be something as simple as Rack, which is a consistent, useful interface between servers. Convention does not and is not tied to monoliths or MVC or any other aspect of Rails.
This is where services like Google Firebase Functions become useful.
I went from having never written a REST API in my life, to up and running in under 20 minutes.
First time I went to create some endpoints on my own server, wow, that was a pain.
I wouldn't quite say that, but I'll agree with your other points. :)
(More than once the docs have been out of date, or just flat out wrong, costing me many hours of development time...)
Yeah, document storage for business-critical data. I'll pass. There's a reason important data gets stored in Postgres.
JS is mess.
Nothing revolutionary, but a good UI lib
It is good to see that the community is open to introspecting and improving even further
I tried making a TypeScript react app around Christmas, I found a tutorial, the commands did not work, I do not remember the details but it was using some bundler and probably the tutorial was a bit old and packages updated in npm. I found a different tutorial, to use create_react_app,
I seen it uses npx(not sure when this tool appeared) it also used tons of dependencies, in the end I created my app from scratch using only the TS compiler package and the react client library, no extra tools, magic, 1 month old tutorials that are outdated already, no install latest tool of the month etc.
Maybe the issue people have is there is no 'js-lang.org' with one tutorial site and getting started. It's a huge community, so of course random blog posts will be a mixed bag of quality.
1 the right tutorial, instruction may not be on top on my search engine, a few months old instructions are too old
2 the create app thing uses tons of "magic", it encourage people not to understand how things work, all is fine until something breaks... here is an issue we hit at work
We have a project that uses gulp(the project is old, I did not started it so don't blame me if gulp is not the state of the art today). One dev added an uglify step to gulp and now the gulp watch t process entered in an infinite loop, I as the one with the most experience I worked on figuring it out, since the uglify step causes the issue I investigate this(I discover that some gulp modules the project uses are obsoleted because a cooler/better one was created but I did not started on upgrading the tools), I read on uglify, it's dependencies, I read on watch it's dependencies, read how it is implemented under the hood and in the end I realize that uhe uglify hstep had the side effect of making the process longer (I suspected that some temp files would be created or other things) but this extra seconds triggered an existing issue in our configuration file, the watch task was watching the output min files but it never triggered before because of a timeout it has(or something similar). In the end I ended up looking under the hood of this magic tools because a dev setup a .json config file wrong but the issue did not manifest until years later.
Conclusion is that magic tools work fine until they do not , then you have to look under the hood or try the reboot,update,change the tool and maybe it is fixed
For tomorrow I need to investigate why npm install package fails to install a package dependencies on a CentOS server, I read that there were some bugs and probably the fixes were not backported and I will have to mess around and understand what is the problem and fix it somehow.
That's my issue (one of many) with the JS ecosystem. Things move so fast that just keeping up feels like a full-time job. I remember giving up on my first approach to React after I followed Swizec's tutorials and quickly hit into some issue with Babel (of all things) that was a week old and transitively screwed up a few months old React/D3 guide.
And, as 'simion314 said, there's way too much magic. create-react-app is a useful spell that (most of the time) makes you a working React app, but I'm not fond of a culture that encourages casting it instead of understanding what's going on and how to actually set up a React project.
That’s hardly unique to Javascript. Back before the internet even existed I’d seen out of date make files which did nothing but spit out linker errors due to API changes in libraries.
I haven't done this exercise in a long while, but the last time I tried to start a project from the "most current and stable releases and recommendations", I ended up not being able to get anything running. In the end, I had several hundred megabytes of libraries downloaded, a complicated configuration, and a non-working application.
Today, there are toolsets to get you started with everything and produce a running application, but it's almost totally opaque. I'm afraid to use them because the first time something breaks, I don't know if I would be able to resolve the issue.
I would still rather have a decent understanding of how things connect.
Do you teach JavaScript first just because of how fast it is to get it up and running (ie. "Just open your web browser")? If I remember correctly it was much more vexing than a lot of compiled / strongly typed languages as the errors in those languages came sooner. In JavaScript there have been times where it loads and runs, but nothing happens, and I had no idea why, which proved frustrating.
I come from an environment (.NET) where setup was a day or two of work but now is a matter of 10 or less minutes).
I agree getting to the browser dev console is instant gratification but I don't view 5 minutes of installation as a punishment from Hell either.
1 week to learn JS latest language features
1 week to grok node, npm and the power of the JS object
1 week for React, basic stuff not redux
1 more week to dabble around
4 weeks and you should be able to be productive JS with its most important flavors. Tell me any other ecosystem where you are that fast.
All things I didn't know how much I relied on until I moved to NodeJS and found them non-existent.
https://writer.zoho.com/writer/open/0y4wx08838bdbcf954b1398c...
With confidential details masked, it's still a pretty good read for the rest of the Internet. Outlines why JS fatigue is not really bad but just improvements and what exactly is stopping us from adopting those improvements.
Resonates a lot with Dan's write-up. Excellent piece by Dan. A much needed one. I'd probably link this along in my proposal.
Note: We've built a pretty fat browser app with plain vanilla JS, strictly ES5 only, crude bash scripts for building a bundled js & all such ancient methods.
Jeez, man, I'm all for minimal tooling too. But ES6 is the lowest hanging fruit there is, I beg you to consider adding a transpile step to your build on your next project so you can use it!
Oh, and code splitting was out of the question. Most modules were attaching themselves to the global namespace (note: a large portion of the app was built even before requireJS was a thing). Which means code-splitting is a developer discipline category, not an automated one.
We have slowly started improving these things though. As I've mentioned in the document, the benefits are beginning to far outweigh the cost now, so yeah we'll move to ES6 soon.
ES5 to ES6 isn't what Java is to Python. It's more like what Python 2 is to Python 3.
There are some coding styles that are popular in esnext that just aren’t practical in es5 because they would be too verbose and not “read” very well.
This is why coffeescript was a godsend. It produced very efficient code too, simpler and faster at runtime than the ES6 replacements.
Especially for those that use the common suggestion for Babel of "last 2 versions of major browsers" presets, the amount of transpiled code has gotten extremely small, and increasingly so.
For example:
Arrow functions: https://caniuse.com/#feat=arrow-functions
ES2015 classes: https://caniuse.com/#feat=es6-class
Async/await: https://caniuse.com/#feat=async-functions
ES2015 modules: https://caniuse.com/#feat=es6-module
«There are some coding styles that are popular in esnext that just aren’t practical in es5 because they would be too verbose and not “read” very well.»
I like to check my code after downleveling in Typescript to ES5 from time to time. There isn't anything in ES2015-ES2018 that downlevels to "unreadable" in Typescript. The "worst" you get is async/await transpiles to ES2015 generators of promises (function*) which then transpiles to ES5 switch/case state machines, but even with all of that downlevel work I think you'd be surprised at how readable it stays.
I had experience with both types of projects - the ones with home made crude build tools (in Python, not bash), and the ones with modern javascript build pipelines. The first build never broke. The second build would break every couple of months for no obvious reason without us touching the project structure.
The problem is opportunity cost. The rest of the tools in the market (Webpack, Rollup) are offering heavier benefits like automatic code splitting, dead code elimination and such things.
Your bespoke bash script has no such community.
I'd bet any of us could find a ton of weird and unintuitive things your app does, as well as it probably being slow to load, hard to use and brittle, in that you'll regularly put out an update that inexplicably breaks something for a day or two.
Add on top that massive extra expense of doing a pure SPA compared to the ease and simplicity of developing a mixed server/front side app, I have no idea why anyone sane ever signs off on a SPA.
And that's before we even get onto the vastly better tooling and development environments that server-side languages have.
For #b SPA is the only option.
The problem is that SPAs are shoehorned on many places where they are absolutely not necessary and only complicate things.
And it was almost perfect (modulo hoisting, semicolon omission) for that.
The trouble has started when Web, as a platform, has failed to provide safe alternative to JS aimed for extendable way of delivering and running high-performant code on the client.
Ideally we should have something like <script type="binary/bytecode"> with something close to JavaVM and HTML DOM exposed to it. At least 15 years ago. So we would have a lot of compilers, static compilation and code analysis.
Instead we have tons of weirdest possible solutions: Web "threads" with code that need to be downloaded and compiled before running, that ugly WebAsm, transpilers-of-something-into-JS. C++ code "transpiled" into JS, in whose nightmare that bright idea was born?
Yet we have crowds of talented people wasting time of writing about how to really HACK the platform that was not meant to be used this way.
Create bunch of problems to ourselves just to overcome them heroically. Far from being productive.
> ugly WebAsm
WASM isn't fully functional as a standalone alternative to JS in the browser, yet, but you can essentially use it that way with things like wasm-bindgen in the Rust ecosystem. And it performs essentially what you're describing, being a VM running bytecode in a sandbox.
"Essentially" is a nice word. You can use it for example as JavaScript is a programming language, essentially, yeah.
W3C DOM was defined initially in terms of Java interfaces.
Where we would be now if we were allowed to run Java bytecodes in browser directly from the very beginning?
<script type="binary/web-bytecode" src="myapp.class">
Today we might discuss -strip-dead-code option in your favorite compiler of XYZ language. Instead of fighting with would-be-linker npm.
We'd be ranting at JVM for not having the features necessary to compile high-perf C code into it, for one.
Which is why Wasm is fundamentally a better approach. It's that one case where it makes sense to go as low level as possible (while retaining cross-platform support), to allow as many future possibilities building on this foundation as possible.
No, we wouldn't fight for how to compile C in it. We would very likely fight to make the payloads and bootstrap times smaller.
[0]https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
IMO the level of Java / Erlang performance is, and should always be, plenty enough for the web.
In 2019 I still have 0 interest in javascript/TS for backend, the thousands of modules under node_modules alone is enough for me, and not all real world product need async/promise/callback/SPA, javascript is over-heated too much, not fun at all.
That Javascript is async-everything is one of its best and often overlooked features in these comparisons.
I think this snippet encapsulates a lot of why Javascript is actually very pleasant on the server:
const results = await Promise.map(urls, (url) => process(url), { concurrency: 8 })
.then((results) => postprocess(results))If you want to look at bolt-on async working, check out C# or Rust. They've basically taken JavaScript's new async/await and added threading (at least Rust has, not sure about C#). You can write an async app and have it run in a thread pool without much fuss.
I don't know what the story is for Java, but seeing as C# is effectively the same thing, it's not hard to imagine adding async being easier than adding threads or performance to JavaScript.
Welcome to the mess :)
Dart? Elm? Clojurescript? Objective-J?
True, maybe everything is different in large scale applications but I hate it if I find something interesting implemented in TypeScript and in 95% of cases I will just move on.
Javascript is not a beauty and any superset just seems like a facelift. The result looks like old and used car tires.
disclaimer: I am no web dev but somehow come in contact with JS frequently.
I'd rather write my own stuff, unless I'm woefully unequipped to to begin with. (Cryptography, authentification, credit card handling...) I feel like I'd learned quite a bit of JavaScript, specifically – especially with the help of someone like Angus Croll [https://javascriptweblog.wordpress.com/].
I'm not that clever a JS developer – or a programmer, for that matter – so his `compose()` and `curry()` sound magical to me.