News for hackers. Stuff that matters.
Re:The melting pot of JavaScript (2017) by orangeeater on Monday January 07, 2019 @04:04PM (#18850056)
> Js barely even supports reflection. This is a huge underrated shortcoming of js if you're doing anything complicated

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.

Re:The melting pot of JavaScript (2017) by orf on Monday January 07, 2019 @04:29PM (#18850331)
> Can you explain what Java offers with regard to reflection that JS doesn't?

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.

Re:The melting pot of JavaScript (2017) by pitaj on Monday January 07, 2019 @05:38PM (#18850992)
> getting the return type of a method and getting the input parameter names (+ types)

Type information literally doesn't exist at runtime, though. Isn't it kind of ridiculous to compare languages like that?

Re:The melting pot of JavaScript (2017) by orf on Monday January 07, 2019 @06:37PM (#18851451)
When you're comparing the relative power of reflection within the language, absolutely not.
Re:The melting pot of JavaScript (2017) by untog on Monday January 07, 2019 @09:45PM (#18852654)
But what would you use that information for, given that the language has no types? A JS function has no guarantees of what type a function returns anyway. It's like taking issue with the fact that a car doesn't come equipped with skis.
Re:The melting pot of JavaScript (2017) by stickfigure on Monday January 07, 2019 @11:42PM (#18853206)
It's like taking issue with the fact that a car doesn't come equipped with skis.

To draw out that analogy... we live in Greenland. Cars with skis are surprisingly useful.

Re:The melting pot of JavaScript (2017) by lopatin on Monday January 07, 2019 @10:14PM (#18852805)
> Type information literally doesn't exist at runtime, though.

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?

Re:The melting pot of JavaScript (2017) by stickfigure on Monday January 07, 2019 @11:45PM (#18853215)
Yes, you are correct. There are also a number of circumstances in which you can get generic type info - it isn't erased, for example, if you create a concrete subclass of a generic type.
Re:The melting pot of JavaScript (2017) by pitaj on Tuesday January 08, 2019 @11:41AM (#18856879)
I was talking about JavaScript. In JavaScript there are no typed functions or arguments, so that information doesn't exist period.
Re:The melting pot of JavaScript (2017) by lopatin on Tuesday January 08, 2019 @01:20PM (#18857924)
Right, so I guess I'm not understanding your point about why comparing two languages like this is ridiculous. Java has a full blown runtime reflection system (it's "types exist at runtime"). JS doesn't. So Java wins in the reflection category.
Re:The melting pot of JavaScript (2017) by tracker1 on Tuesday January 08, 2019 @03:43PM (#18859479)
But in JS, reflection is pretty much not needed... I don't need to use reflection to see if an object has a quack method, or that I call it with the right types... I just call instance.quack() ... It's up to you as the developer to keep your interfaces and composition in line.

It's actually WAY easier than with C# or Java. Since the use-case of reflection itself is largely unnecessary.

Re:The melting pot of JavaScript (2017) by lopatin on Saturday January 12, 2019 @09:46PM (#18894719)
Calling a method and seeing what happens is not a substitute for reflection. You can do that in Java too btw.
Re:The melting pot of JavaScript (2017) by orangeeater on Monday January 07, 2019 @04:31PM (#18850348)
> 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.

Ah, that's quite cool.

Re:The melting pot of JavaScript (2017) by orf on Monday January 07, 2019 @04:42PM (#18850463)
You can do almost anything with Java reflection, JS really pales in comparison.

Which in some ways is a good thing as you can do a lot more optimizations.

Re:The melting pot of JavaScript (2017) by spricket on Monday January 07, 2019 @04:35PM (#18850406)
Typeof is a good one, but holy crap I had no idea return type and param support was that horrific
Re:The melting pot of JavaScript (2017) by spricket on Monday January 07, 2019 @04:27PM (#18850310)
Java uses reflection and annotations to support all kinds of language extensions. Js has a lot of nasty issues with the "prototype chain" and annotation support is still experimental. For example, in java, scanning your classes and their annotations to generate code for them at compile time is a standardized feature.

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.

Re:The melting pot of JavaScript (2017) by kangoo1707 on Monday January 07, 2019 @05:52PM (#18851102)
Do you have any concrete example for "For example, in java, scanning your classes and their annotations to generate code for them at compile time is a standardized feature"?

Tip: in JS, I don't want OOP class. If you really want class, could you show me the intention behind it?

Re:The melting pot of JavaScript (2017) by gwright on Monday January 07, 2019 @07:46PM (#18851859)
In general this what java annotation processors are all about. As a specific example, Dagger, a compile time, type safe dependency injection framework. https://google.github.io/dagger/
Re:The melting pot of JavaScript (2017) by spricket on Monday January 07, 2019 @10:00PM (#18852726)
Java only works in classes :) . They're actually the compilation unit as well so no way around it. (Files are compiled a .class file at a time from single source files)

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.

Re:The melting pot of JavaScript (2017) by stickfigure on Tuesday January 08, 2019 @12:19AM (#18853388)
Every popular ORM uses reflection to determine how to map fields to columns. For example, what type of date or money object to use.

I automagically map some postgres JSONB columns to a parsed object form. Looks just like a regular typed nested object.

Re:The melting pot of JavaScript (2017) by hajile on Tuesday January 08, 2019 @12:28AM (#18853431)
That's a solution looking for a problem in JS. You're thinking in types instead of in terms of a dynamic language.

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).

Re:The melting pot of JavaScript (2017) by stickfigure on Tuesday January 08, 2019 @01:05AM (#18853618)
you can look everything over at runtime

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.

Re:The melting pot of JavaScript (2017) by joshuamorton on Tuesday January 08, 2019 @02:52AM (#18854013)
> Well-written Java programs are generally more concise and less verbose than well-written JS/Python/Ruby programs.

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.

Re:The melting pot of JavaScript (2017) by stickfigure on Wednesday January 09, 2019 @08:02PM (#18870630)
> This isn't at all true.

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.

Re:The melting pot of JavaScript (2017) by joshuamorton on Wednesday January 09, 2019 @08:35PM (#18870774)
> This is vanilla Java.

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-...

Re:The melting pot of JavaScript (2017) by stickfigure on Thursday January 10, 2019 @12:15AM (#18871706)
I'm not quite sure what you're getting at with the "No, it's Java EE" comment. JAX-RS is a Java standard, with several implementations, and you don't need a "Java EE Server" or anything magical like that to use it. And that link to the Custom Marshalling section of the JAX-RS docs is a little weird; my example doesn't require monkeying with low-level stuff like that and most users don't.

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.

Re:The melting pot of JavaScript (2017) by joshuamorton on Thursday January 10, 2019 @01:23AM (#18871940)
>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.

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 myself

1. 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

Re:The melting pot of JavaScript (2017) by stickfigure on Thursday January 10, 2019 @02:44AM (#18872223)
The Java equivalent of your example is probably:

    @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.

Re:The melting pot of JavaScript (2017) by joshuamorton on Thursday January 10, 2019 @02:55AM (#18872267)
> The Java equivalent of your example is probably

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.

Re:The melting pot of JavaScript (2017) by tracker1 on Tuesday January 08, 2019 @03:47PM (#18859510)
Why do I need to manually convert anything? Even then...

    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.

Re:The melting pot of JavaScript (2017) by stickfigure on Wednesday January 09, 2019 @07:43PM (#18870541)
Did a date column get mapped to Date, moment, date-fns, luxon, or any of the dozen other choices that your shop might standardize on?

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.

Re:The melting pot of JavaScript (2017) by tmerse on Tuesday January 08, 2019 @12:45AM (#18853524)
You should have a look at typeorm [1]. Typescript ORM with decorator support.

1: http://typeorm.io/

Re:The melting pot of JavaScript (2017) by stickfigure on Tuesday January 08, 2019 @01:24AM (#18853702)
That's cool, and will keep it in mind for the next time I work on a node project.

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>

Re:The melting pot of JavaScript (2017) by gwright on Monday January 07, 2019 @07:47PM (#18851865)
Retrofit is another example: https://square.github.io/retrofit/
Re:The melting pot of JavaScript (2017) by buerkle on Monday January 07, 2019 @06:19PM (#18851326)
http://immutables.github.io/ makes great use of this feature in Java
Re:The melting pot of JavaScript (2017) by hombre_fatal on Monday January 07, 2019 @06:06PM (#18851218)
One example would be a url router for a web server that turns the url variables into the handler's expected argument type and ignores requests that do not.

    router.get('/users/:id', (id: UUID) => ...)
    router.get('/products/:id', (id: Int) => ...)
Re:The melting pot of JavaScript (2017) by tracker1 on Tuesday January 08, 2019 @03:52PM (#18859565)
That would be relatively easy to do something very similar with middleware for express/koa

    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

Re:The melting pot of JavaScript (2017) by snek on Monday January 07, 2019 @05:45PM (#18851043)
Just to be clear, Reflect exists to be direct interface to JS's Module Object Protocol (MOP). Every "primitive" operation you can perform on an object in js, (such as adding a property or getting the value of a property), is exposed via Reflect.
Re:The melting pot of JavaScript (2017) by chii on Monday January 07, 2019 @05:57PM (#18851147)
There's no easy way to inspect the runtime in js to find all functions or all classes that can be loaded/called.

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.

Re:The melting pot of JavaScript (2017) by est on Monday January 07, 2019 @10:41PM (#18852940)
> Can you explain what Java offers with regard to reflection that JS doesn't?

One thing comes to mind, how to twinkle stuff inside closures?