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